mirror of https://github.com/rm-dr/daisy
Added prefix foundation
parent
600c5f76cc
commit
1f0f7e0ac9
|
@ -13,6 +13,7 @@ use crate::parser::treeify::treeify;
|
||||||
use crate::parser::find_subs::find_subs;
|
use crate::parser::find_subs::find_subs;
|
||||||
|
|
||||||
use crate::quantity::Quantity;
|
use crate::quantity::Quantity;
|
||||||
|
use crate::quantity::Unit;
|
||||||
|
|
||||||
use crate::tokens::Token;
|
use crate::tokens::Token;
|
||||||
|
|
||||||
|
@ -112,8 +113,7 @@ impl PreToken {
|
||||||
return Ok(Token::Constant(a, b));
|
return Ok(Token::Constant(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
let c = Quantity::from_unit_string(&s);
|
let c = Unit::from_string(&s);
|
||||||
|
|
||||||
if c.is_some() { return Ok(Token::Number(c.unwrap())); }
|
if c.is_some() { return Ok(Token::Number(c.unwrap())); }
|
||||||
|
|
||||||
return Err((l, ParserError::Undefined(s)));
|
return Err((l, ParserError::Undefined(s)));
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub(in crate::quantity) use crate::quantity::scalar::Scalar;
|
||||||
|
|
||||||
mod unit;
|
mod unit;
|
||||||
pub use crate::quantity::unit::Unit;
|
pub use crate::quantity::unit::Unit;
|
||||||
pub use crate::quantity::unit::BaseUnit;
|
pub use crate::quantity::unit::FreeUnit;
|
||||||
|
|
||||||
mod quantity;
|
mod quantity;
|
||||||
pub use crate::quantity::quantity::Quantity;
|
pub use crate::quantity::quantity::Quantity;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::ops::{
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::quantity::Unit;
|
use crate::quantity::Unit;
|
||||||
use crate::quantity::BaseUnit;
|
use crate::quantity::FreeUnit;
|
||||||
|
|
||||||
use crate::quantity::Scalar;
|
use crate::quantity::Scalar;
|
||||||
|
|
||||||
|
@ -89,38 +89,10 @@ impl Quantity {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_unit(&mut self, ui: BaseUnit, pi: Scalar) { self.u.insert(ui, pi) }
|
pub fn insert_unit(&mut self, ui: FreeUnit, pi: Scalar) { self.u.insert(ui, pi) }
|
||||||
pub fn set_unit(&mut self, u: Unit) { self.u = u; }
|
pub fn set_unit(&mut self, u: Unit) { self.u = u; }
|
||||||
|
|
||||||
pub fn from_unit_string(s: &str) -> Option<Quantity> {
|
|
||||||
// Base Units
|
|
||||||
let b = match s {
|
|
||||||
"m" => Some(BaseUnit::Meter),
|
|
||||||
"s" => Some(BaseUnit::Second),
|
|
||||||
"kg" => Some(BaseUnit::Kilogram),
|
|
||||||
"a" => Some(BaseUnit::Ampere),
|
|
||||||
"k" => Some(BaseUnit::Kelvin),
|
|
||||||
"mol" => Some(BaseUnit::Mole),
|
|
||||||
"c" => Some(BaseUnit::Candela),
|
|
||||||
"ft" => Some(BaseUnit::Foot),
|
|
||||||
"mile" => Some(BaseUnit::Mile),
|
|
||||||
"hour" => Some(BaseUnit::Hour),
|
|
||||||
"min" => Some(BaseUnit::Minute),
|
|
||||||
_ => { None }
|
|
||||||
};
|
|
||||||
|
|
||||||
if b.is_some() {
|
|
||||||
let mut u = Unit::new();
|
|
||||||
u.insert(b.unwrap(), Scalar::new_rational(1f64).unwrap());
|
|
||||||
|
|
||||||
let mut q = Quantity::new_rational(1f64).unwrap();
|
|
||||||
q.set_unit(u);
|
|
||||||
|
|
||||||
return Some(q);
|
|
||||||
};
|
|
||||||
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
||||||
|
@ -132,7 +104,6 @@ impl Quantity {
|
||||||
|
|
||||||
return Some(r);
|
return Some(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::f32::consts::E;
|
||||||
use std::ops::{
|
use std::ops::{
|
||||||
Mul, Div,
|
Mul, Div,
|
||||||
MulAssign, DivAssign
|
MulAssign, DivAssign
|
||||||
|
@ -7,29 +8,194 @@ use std::ops::{
|
||||||
use super::Scalar;
|
use super::Scalar;
|
||||||
use super::Quantity;
|
use super::Quantity;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Debug)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum BaseUnit {
|
#[derive(Eq, PartialEq)]
|
||||||
|
pub enum UnitBase {
|
||||||
|
// Base Units
|
||||||
Second,
|
Second,
|
||||||
Meter,
|
Meter,
|
||||||
Kilogram,
|
Gram, // Technically kilogram, but that messes with prefix architecture.
|
||||||
Ampere,
|
Ampere,
|
||||||
Kelvin,
|
Kelvin,
|
||||||
Mole,
|
Mole,
|
||||||
Candela,
|
Candela,
|
||||||
|
|
||||||
|
// Length units
|
||||||
|
Inch,
|
||||||
Foot,
|
Foot,
|
||||||
Mile,
|
Mile,
|
||||||
|
|
||||||
|
// Time units
|
||||||
Minute,
|
Minute,
|
||||||
Hour
|
Hour,
|
||||||
|
Day,
|
||||||
|
//Week,
|
||||||
|
//Month,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseUnit {
|
#[derive(Hash)]
|
||||||
pub fn to_base(&self) -> Option<Quantity> {
|
#[derive(Debug)]
|
||||||
match self {
|
#[derive(Copy, Clone)]
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
pub enum Prefix {
|
||||||
|
None,
|
||||||
|
|
||||||
|
Quetta,
|
||||||
|
Ronna,
|
||||||
|
Yotta,
|
||||||
|
Zetta,
|
||||||
|
Exa,
|
||||||
|
Peta,
|
||||||
|
Tera,
|
||||||
|
Giga,
|
||||||
|
Mega,
|
||||||
|
Kilo,
|
||||||
|
Hecto,
|
||||||
|
Deka,
|
||||||
|
|
||||||
|
Deci,
|
||||||
|
Centi,
|
||||||
|
Milli,
|
||||||
|
Micro,
|
||||||
|
Nano,
|
||||||
|
Pico,
|
||||||
|
Femto,
|
||||||
|
Atto,
|
||||||
|
Zepto,
|
||||||
|
Yocto,
|
||||||
|
Ronto,
|
||||||
|
Quecto
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prefix {
|
||||||
|
pub fn to_ratio(&self) -> Quantity {
|
||||||
|
let q = Quantity::new_rational_from_string(match self {
|
||||||
|
Prefix::Quetta => "1e30",
|
||||||
|
Prefix::Ronna => "1e27",
|
||||||
|
Prefix::Yotta => "1e24",
|
||||||
|
Prefix::Zetta => "1e21",
|
||||||
|
Prefix::Exa => "1e18",
|
||||||
|
Prefix::Peta => "1e15",
|
||||||
|
Prefix::Tera => "1e12",
|
||||||
|
Prefix::Giga => "1e9",
|
||||||
|
Prefix::Mega => "1e6",
|
||||||
|
Prefix::Kilo => "1e3",
|
||||||
|
Prefix::Hecto => "1e2",
|
||||||
|
Prefix::Deka => "1e1",
|
||||||
|
|
||||||
|
Prefix::Deci => "1e-1",
|
||||||
|
Prefix::Centi => "1e-2",
|
||||||
|
Prefix::Milli => "1e-3",
|
||||||
|
Prefix::Micro => "1e-6",
|
||||||
|
Prefix::Nano => "1e-9",
|
||||||
|
Prefix::Pico => "1e-12",
|
||||||
|
Prefix::Femto => "1e-15",
|
||||||
|
Prefix::Atto => "1e-18",
|
||||||
|
Prefix::Zepto => "1e-21",
|
||||||
|
Prefix::Yocto => "1e-24",
|
||||||
|
Prefix::Ronto => "1e-27",
|
||||||
|
Prefix::Quecto => "1e-30",
|
||||||
|
|
||||||
|
Prefix::None => { "1" }
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
return q;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for Prefix {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
String::from(match self {
|
||||||
|
Prefix::Quetta => "Q",
|
||||||
|
Prefix::Ronna => "R",
|
||||||
|
Prefix::Yotta => "Y",
|
||||||
|
Prefix::Zetta => "Z",
|
||||||
|
Prefix::Exa => "E",
|
||||||
|
Prefix::Peta => "P",
|
||||||
|
Prefix::Tera => "T",
|
||||||
|
Prefix::Giga => "G",
|
||||||
|
Prefix::Mega => "M",
|
||||||
|
Prefix::Kilo => "k",
|
||||||
|
Prefix::Hecto => "h",
|
||||||
|
Prefix::Deka => "da",
|
||||||
|
|
||||||
|
Prefix::Deci => "d",
|
||||||
|
Prefix::Centi => "c",
|
||||||
|
Prefix::Milli => "m",
|
||||||
|
Prefix::Micro => "u",
|
||||||
|
Prefix::Nano => "n",
|
||||||
|
Prefix::Pico => "p",
|
||||||
|
Prefix::Femto => "f",
|
||||||
|
Prefix::Atto => "a",
|
||||||
|
Prefix::Zepto => "z",
|
||||||
|
Prefix::Yocto => "y",
|
||||||
|
Prefix::Ronto => "r",
|
||||||
|
Prefix::Quecto => "q",
|
||||||
|
|
||||||
|
Prefix::None => ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Hash)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
pub struct FreeUnit {
|
||||||
|
u: UnitBase,
|
||||||
|
p: Prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! quick_base_factor {
|
||||||
|
(float, $u:expr, $s:expr, $( ($x:expr, $p:expr) ),* ) => {
|
||||||
|
Some(Quantity {
|
||||||
|
v: Scalar::new_float_from_string($s).unwrap(),
|
||||||
|
u: Unit::from_array(&[
|
||||||
|
$(
|
||||||
|
(FreeUnit::from_base($x), Scalar::new_rational($p).unwrap()),
|
||||||
|
)*
|
||||||
|
(FreeUnit::from_base($u), Scalar::new_rational(-1f64).unwrap())
|
||||||
|
])
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
(rational, $u:expr, $s:expr, $( ($x:expr, $p:expr) ),* ) => {
|
||||||
|
Some(Quantity {
|
||||||
|
v: Scalar::new_float_from_string($s).unwrap(),
|
||||||
|
u: Unit::from_array(&[
|
||||||
|
$(
|
||||||
|
(FreeUnit::from_base($x), Scalar::new_rational($p).unwrap()),
|
||||||
|
)*
|
||||||
|
(FreeUnit::from_base($u), Scalar::new_rational(-1f64).unwrap())
|
||||||
|
])
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl FreeUnit {
|
||||||
|
pub fn from_base(u: UnitBase) -> FreeUnit {
|
||||||
|
return FreeUnit {
|
||||||
|
u,
|
||||||
|
p: Prefix::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_base_prefix(u: UnitBase, p: Prefix) -> FreeUnit {
|
||||||
|
return FreeUnit { u, p }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_prefix(&mut self, p: Prefix) {
|
||||||
|
self.p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_base_factor(&self) -> Quantity {
|
||||||
|
let q = match self.u {
|
||||||
// Returns the unit we need to multiply by to get a base
|
// Returns the unit we need to multiply by to get a base
|
||||||
// unit, or `None` if this is already a base unit.
|
// unit, or `None` if this is already a base unit.
|
||||||
//
|
//
|
||||||
|
@ -39,55 +205,92 @@ impl BaseUnit {
|
||||||
//
|
//
|
||||||
// The units here MUST be in terms of base units.
|
// The units here MUST be in terms of base units.
|
||||||
// If they aren't, things will break.
|
// If they aren't, things will break.
|
||||||
BaseUnit::Foot => Some(Quantity {
|
|
||||||
v: Scalar::new_float_from_string("0.3048").unwrap(),
|
|
||||||
u: Unit::from_array(&[
|
|
||||||
(BaseUnit::Meter, Scalar::new_rational(1f64).unwrap()),
|
|
||||||
(BaseUnit::Foot, Scalar::new_rational(-1f64).unwrap())
|
|
||||||
])
|
|
||||||
}),
|
|
||||||
|
|
||||||
BaseUnit::Mile => Some(Quantity {
|
UnitBase::Foot => quick_base_factor!(float,
|
||||||
v: Scalar::new_float_from_string("1609").unwrap(),
|
UnitBase::Foot,
|
||||||
u: Unit::from_array(&[
|
"0.3048",
|
||||||
(BaseUnit::Meter, Scalar::new_rational(1f64).unwrap()),
|
(UnitBase::Meter, 1f64)
|
||||||
(BaseUnit::Mile, Scalar::new_rational(-1f64).unwrap())
|
),
|
||||||
])
|
|
||||||
}),
|
|
||||||
|
|
||||||
|
UnitBase::Inch => quick_base_factor!(float,
|
||||||
|
UnitBase::Inch,
|
||||||
|
"0.0254",
|
||||||
|
(UnitBase::Meter, 1f64)
|
||||||
|
),
|
||||||
|
|
||||||
BaseUnit::Minute => Some(Quantity {
|
UnitBase::Mile => quick_base_factor!(rational,
|
||||||
v: Scalar::new_rational_from_string("60").unwrap(),
|
UnitBase::Mile,
|
||||||
u: Unit::from_array(&[
|
"1609",
|
||||||
(BaseUnit::Second, Scalar::new_rational(1f64).unwrap()),
|
(UnitBase::Meter, 1f64)
|
||||||
(BaseUnit::Minute, Scalar::new_rational(-1f64).unwrap())
|
),
|
||||||
])
|
|
||||||
}),
|
|
||||||
|
|
||||||
|
UnitBase::Minute => quick_base_factor!(rational,
|
||||||
|
UnitBase::Minute,
|
||||||
|
"60",
|
||||||
|
(UnitBase::Second, 1f64)
|
||||||
|
),
|
||||||
|
|
||||||
BaseUnit::Hour => Some(Quantity {
|
UnitBase::Hour => quick_base_factor!(rational,
|
||||||
v: Scalar::new_rational_from_string("3600").unwrap(),
|
UnitBase::Hour,
|
||||||
u: Unit::from_array(&[
|
"3600",
|
||||||
(BaseUnit::Second, Scalar::new_rational(1f64).unwrap()),
|
(UnitBase::Second, 1f64)
|
||||||
(BaseUnit::Hour, Scalar::new_rational(-1f64).unwrap())
|
),
|
||||||
])
|
|
||||||
}),
|
UnitBase::Day => quick_base_factor!(rational,
|
||||||
|
UnitBase::Day,
|
||||||
|
"86400",
|
||||||
|
(UnitBase::Second, 1f64)
|
||||||
|
),
|
||||||
|
|
||||||
// Only base units should be missing a conversion factor.
|
// Only base units should be missing a conversion factor.
|
||||||
_ => None
|
_ => None
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let mut q = q.unwrap_or(Quantity::new_rational_from_string("1").unwrap());
|
||||||
|
|
||||||
|
let mut p = self.p.to_ratio();
|
||||||
|
p.insert_unit(FreeUnit::from_base(self.u), Scalar::new_rational(1f64).unwrap());
|
||||||
|
p.insert_unit(FreeUnit::from_base_prefix(self.u, self.p), Scalar::new_rational(-1f64).unwrap());
|
||||||
|
q *= p;
|
||||||
|
|
||||||
|
return q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ToString for FreeUnit {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
let s = match self.u {
|
||||||
|
UnitBase::Second => "s",
|
||||||
|
UnitBase::Meter => "m",
|
||||||
|
UnitBase::Gram => "g",
|
||||||
|
UnitBase::Ampere => "a",
|
||||||
|
UnitBase::Kelvin => "k",
|
||||||
|
UnitBase::Mole => "mol",
|
||||||
|
UnitBase::Candela => "c",
|
||||||
|
|
||||||
|
UnitBase::Foot => "ft",
|
||||||
|
UnitBase::Inch => "in",
|
||||||
|
UnitBase::Mile => "mile",
|
||||||
|
|
||||||
|
UnitBase::Hour => "hour",
|
||||||
|
UnitBase::Minute => "min",
|
||||||
|
UnitBase::Day => "day",
|
||||||
|
};
|
||||||
|
|
||||||
|
let p = self.p.to_string();
|
||||||
|
|
||||||
|
format!("{p}{s}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Unit {
|
pub struct Unit {
|
||||||
// Unit, power.
|
// Unit, power.
|
||||||
pub val: HashMap<BaseUnit, Scalar>
|
pub val: HashMap<FreeUnit, Scalar>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl ToString for Unit {
|
impl ToString for Unit {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
if self.unitless() { return String::new(); };
|
if self.unitless() { return String::new(); };
|
||||||
|
@ -95,7 +298,7 @@ impl ToString for Unit {
|
||||||
let mut top_empty = true;
|
let mut top_empty = true;
|
||||||
let mut bottom_empty = true;
|
let mut bottom_empty = true;
|
||||||
|
|
||||||
for (_, p) in &self.val {
|
for (_, p) in self.get_val() {
|
||||||
if p.is_positive() {
|
if p.is_positive() {
|
||||||
top_empty = false;
|
top_empty = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,21 +309,8 @@ impl ToString for Unit {
|
||||||
let mut t = String::new();
|
let mut t = String::new();
|
||||||
let mut b = String::new();
|
let mut b = String::new();
|
||||||
|
|
||||||
for (u, p) in &self.val {
|
for (u, p) in self.get_val() {
|
||||||
let c = match u {
|
let c = u.to_string();
|
||||||
BaseUnit::Second => "s",
|
|
||||||
BaseUnit::Meter => "m",
|
|
||||||
BaseUnit::Kilogram => "kg",
|
|
||||||
BaseUnit::Ampere => "a",
|
|
||||||
BaseUnit::Kelvin => "k",
|
|
||||||
BaseUnit::Mole => "mol",
|
|
||||||
BaseUnit::Candela => "c",
|
|
||||||
|
|
||||||
BaseUnit::Foot => "ft",
|
|
||||||
BaseUnit::Mile => "mile",
|
|
||||||
BaseUnit::Hour => "hour",
|
|
||||||
BaseUnit::Minute => "min",
|
|
||||||
};
|
|
||||||
|
|
||||||
if *p == Scalar::new_rational(1f64).unwrap() {
|
if *p == Scalar::new_rational(1f64).unwrap() {
|
||||||
t.push_str(&format!("{c}·"));
|
t.push_str(&format!("{c}·"));
|
||||||
|
@ -153,14 +343,16 @@ impl ToString for Unit {
|
||||||
|
|
||||||
|
|
||||||
impl Unit {
|
impl Unit {
|
||||||
|
|
||||||
pub fn new() -> Unit {
|
pub fn new() -> Unit {
|
||||||
return Unit{
|
return Unit {
|
||||||
val: HashMap::new()
|
val: HashMap::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_array(a: &[(BaseUnit, Scalar)]) -> Unit {
|
pub fn get_val(&self) -> &HashMap<FreeUnit, Scalar> { &self.val }
|
||||||
|
pub fn get_val_mut(&mut self) -> &mut HashMap<FreeUnit, Scalar> { &mut self.val }
|
||||||
|
|
||||||
|
pub fn from_array(a: &[(FreeUnit, Scalar)]) -> Unit {
|
||||||
let mut n = Unit::new();
|
let mut n = Unit::new();
|
||||||
for (u, p) in a.iter() {
|
for (u, p) in a.iter() {
|
||||||
n.insert(*u, p.clone());
|
n.insert(*u, p.clone());
|
||||||
|
@ -168,37 +360,87 @@ impl Unit {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unitless(&self) -> bool { self.val.len() == 0 }
|
pub fn unitless(&self) -> bool { self.get_val().len() == 0 }
|
||||||
|
|
||||||
pub fn insert(&mut self, u: BaseUnit, p: Scalar) {
|
pub fn insert(&mut self, u: FreeUnit, p: Scalar) {
|
||||||
match self.val.get_mut(&u) {
|
let v = self.get_val_mut();
|
||||||
|
match v.get_mut(&u) {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
let n = i.clone() + p;
|
let n = i.clone() + p;
|
||||||
|
|
||||||
if n.is_zero() {
|
if n.is_zero() {
|
||||||
self.val.remove(&u);
|
v.remove(&u);
|
||||||
} else { *i = n; }
|
} else { *i = n; }
|
||||||
},
|
},
|
||||||
None => { self.val.insert(u, p); }
|
None => { v.insert(u, p); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pow(&self, pwr: Scalar) -> Unit {
|
pub fn pow(&self, pwr: Scalar) -> Unit {
|
||||||
let mut u = self.clone();
|
let mut u = self.clone();
|
||||||
for (_, p) in &mut u.val {
|
for (_, p) in u.get_val_mut() {
|
||||||
*p *= pwr.clone();
|
*p *= pwr.clone();
|
||||||
};
|
};
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn from_string(s: &str) -> Option<Quantity> {
|
||||||
|
// Base Units
|
||||||
|
let b = match s {
|
||||||
|
"m" => Some(UnitBase::Meter),
|
||||||
|
"s" => Some(UnitBase::Second),
|
||||||
|
"sec" => Some(UnitBase::Second),
|
||||||
|
"g" => Some(UnitBase::Gram),
|
||||||
|
"a" => Some(UnitBase::Ampere),
|
||||||
|
"k" => Some(UnitBase::Kelvin),
|
||||||
|
"mol" => Some(UnitBase::Mole),
|
||||||
|
"c" => Some(UnitBase::Candela),
|
||||||
|
"ft" => Some(UnitBase::Foot),
|
||||||
|
"mile" => Some(UnitBase::Mile),
|
||||||
|
"hour" => Some(UnitBase::Hour),
|
||||||
|
"min" => Some(UnitBase::Minute),
|
||||||
|
"day" => Some(UnitBase::Day),
|
||||||
|
_ => { None }
|
||||||
|
};
|
||||||
|
|
||||||
|
if b.is_some() {
|
||||||
|
let mut u = Unit::new();
|
||||||
|
let b = FreeUnit::from_base(b.unwrap());
|
||||||
|
|
||||||
|
u.insert(b, Scalar::new_rational(1f64).unwrap());
|
||||||
|
|
||||||
|
let mut q = Quantity::new_rational(1f64).unwrap();
|
||||||
|
q.set_unit(u);
|
||||||
|
|
||||||
|
return Some(q);
|
||||||
|
};
|
||||||
|
|
||||||
|
if b.is_none() {
|
||||||
|
if s == "kg" {
|
||||||
|
let mut u = Unit::new();
|
||||||
|
let mut b = FreeUnit::from_base(UnitBase::Gram);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn to_base_factor(&self) -> Quantity {
|
pub fn to_base_factor(&self) -> Quantity {
|
||||||
let mut q = Quantity::new_rational(1f64).unwrap();
|
let mut q = Quantity::new_rational(1f64).unwrap();
|
||||||
|
|
||||||
for (u, p) in self.val.iter() {
|
for (u, p) in self.get_val().iter() {
|
||||||
let b = u.to_base();
|
let b = u.to_base_factor();
|
||||||
if b.is_some() {
|
q *= b.pow(Quantity::from_scalar(p.clone()));
|
||||||
q *= b.unwrap().pow(Quantity::from_scalar(p.clone()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return q;
|
return q;
|
||||||
|
@ -208,8 +450,9 @@ impl Unit {
|
||||||
|
|
||||||
impl PartialEq for Unit {
|
impl PartialEq for Unit {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
for (u, p) in &other.val {
|
let v = self.get_val();
|
||||||
match self.val.get(u) {
|
for (u, p) in other.get_val() {
|
||||||
|
match v.get(u) {
|
||||||
Some(i) => { if i != p { return false; } },
|
Some(i) => { if i != p { return false; } },
|
||||||
None => { return false; }
|
None => { return false; }
|
||||||
};
|
};
|
||||||
|
@ -223,14 +466,14 @@ impl Mul for Unit {
|
||||||
|
|
||||||
fn mul(self, other: Self) -> Self::Output {
|
fn mul(self, other: Self) -> Self::Output {
|
||||||
let mut o = self.clone();
|
let mut o = self.clone();
|
||||||
for (u, p) in &other.val { o.insert(*u, p.clone()); }
|
for (u, p) in other.get_val() { o.insert(*u, p.clone()); }
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MulAssign for Unit where {
|
impl MulAssign for Unit where {
|
||||||
fn mul_assign(&mut self, other: Self) {
|
fn mul_assign(&mut self, other: Self) {
|
||||||
for (u, p) in &other.val { self.insert(*u, p.clone()); }
|
for (u, p) in other.get_val() { self.insert(*u, p.clone()); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,13 +482,13 @@ impl Div for Unit {
|
||||||
|
|
||||||
fn div(self, other: Self) -> Self::Output {
|
fn div(self, other: Self) -> Self::Output {
|
||||||
let mut o = self.clone();
|
let mut o = self.clone();
|
||||||
for (u, p) in &other.val { o.insert(*u, -p.clone()); }
|
for (u, p) in other.get_val() { o.insert(*u, -p.clone()); }
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DivAssign for Unit where {
|
impl DivAssign for Unit where {
|
||||||
fn div_assign(&mut self, other: Self) {
|
fn div_assign(&mut self, other: Self) {
|
||||||
for (u, p) in &other.val { self.insert(*u, -p.clone()); }
|
for (u, p) in other.get_val() { self.insert(*u, -p.clone()); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue