Compound unit foundation

pull/2/head
Mark 2023-04-10 21:03:16 -07:00
parent ad3ae83c66
commit 175261b5c0
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
4 changed files with 94 additions and 33 deletions

View File

@ -93,31 +93,30 @@ impl PreToken {
let c = match &s[..] { let c = match &s[..] {
// Mathematical constants // Mathematical constants
// 100 digits of each. // 100 digits of each.
"π"|"pi" => { Some(Token::Constant(Quantity::new_float_from_string( "π"|"pi" => { Some((Quantity::new_float_from_string(
"3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067" "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067"
).unwrap(), String::from("π")))}, ).unwrap(), String::from("π")))},
"e" => { Some(Token::Constant(Quantity::new_float_from_string( "e" => { Some((Quantity::new_float_from_string(
"2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427" "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427"
).unwrap(), String::from("e"))) }, ).unwrap(), String::from("e"))) },
"phi"|"φ" => { Some(Token::Constant(Quantity::new_float_from_string( "phi"|"φ" => { Some((Quantity::new_float_from_string(
"1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137" "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137"
).unwrap(), String::from("φ"))) }, ).unwrap(), String::from("φ"))) },
_ => { None } _ => { None }
}; };
if c.is_some() { return Ok(c.unwrap()); }
let c = Unit::from_string(&s);
if c.is_some() { if c.is_some() {
let mut q = Quantity::new_rational(1f64).unwrap(); let (a, b) = c.unwrap();
q.set_unit(c.unwrap()); return Ok(Token::Constant(a, b));
return Ok(Token::Number(q));
} }
let c = Quantity::from_unit_string(&s);
if c.is_some() { return Ok(Token::Number(c.unwrap())); }
return Err((l, ParserError::Undefined(s))); return Err((l, ParserError::Undefined(s)));
} }

View File

@ -22,6 +22,11 @@ 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::BaseUnit;
pub(in crate::quantity) use crate::quantity::unit::CompoundUnit;
mod quantity; mod quantity;
pub use crate::quantity::quantity::Quantity; pub use crate::quantity::quantity::Quantity;

View File

@ -7,9 +7,9 @@ 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::BaseUnit;
use crate::quantity::CompoundUnit;
use crate::quantity::Scalar; use crate::quantity::Scalar;
@ -44,8 +44,6 @@ impl Quantity {
return format!("{n} {u}"); return format!("{n} {u}");
} }
pub fn new_float(f: f64) -> Option<Quantity> { pub fn new_float(f: f64) -> Option<Quantity> {
let v = Scalar::new_float(f); let v = Scalar::new_float(f);
if v.is_none() { return None; } if v.is_none() { return None; }
@ -88,6 +86,48 @@ impl Quantity {
pub fn insert_unit(&mut self, ui: BaseUnit, pi: f64) { self.u.insert(ui, pi) } pub fn insert_unit(&mut self, ui: BaseUnit, pi: f64) { 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),
_ => { None }
};
if b.is_some() {
let mut u = Unit::new();
u.insert(b.unwrap(), 1f64);
let mut q = Quantity::new_rational(1f64).unwrap();
q.set_unit(u);
return Some(q);
};
// Compound units
let b = match s {
"ft" => Some(CompoundUnit::FOOT),
_ => { None }
};
if b.is_some() {
let b = b.unwrap();
let q = Quantity{
v: b.coef(),
u: b.unit()
};
return Some(q);
};
return None;
}
} }

View File

@ -1,11 +1,11 @@
use std::{collections::HashMap, hash::Hash}; use std::collections::HashMap;
use std::ops::{ use std::ops::{
Mul, Div, Mul, Div,
MulAssign, DivAssign MulAssign, DivAssign
}; };
use crate::quantity::Scalar;
#[derive(Debug)] #[derive(Debug)]
#[derive(Hash)] #[derive(Hash)]
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]
@ -20,6 +20,40 @@ pub enum BaseUnit {
Candela Candela
} }
pub struct CompoundUnit {
coef_str: &'static str,
rational: bool,
units: &'static[(BaseUnit, f64)],
pub str: &'static str
}
impl CompoundUnit {
pub const FOOT: CompoundUnit = CompoundUnit {
coef_str: "0.3048",
rational: false,
units: &[(BaseUnit::Meter, 1f64)],
str: "ft"
};
pub fn unit(&self) -> Unit {
let mut n = Unit::new();
for (u, p) in self.units.iter() {
n.insert(*u, *p);
}
return n;
}
pub fn coef(&self) -> Scalar {
if self.rational {
Scalar::new_rational_from_string(self.coef_str).unwrap()
} else {
Scalar::new_float_from_string(self.coef_str).unwrap()
}
}
}
#[derive(Debug)] #[derive(Debug)]
#[derive(Clone)] #[derive(Clone)]
pub struct Unit { pub struct Unit {
@ -117,23 +151,6 @@ impl Unit {
}; };
return u; return u;
} }
pub fn from_string(s: &str) -> Option<Unit> {
let b = match s {
"m" => BaseUnit::Meter,
"s" => BaseUnit::Second,
"kg" => BaseUnit::Kilogram,
"a" => BaseUnit::Ampere,
"k" => BaseUnit::Kelvin,
"mol" => BaseUnit::Mole,
"c" => BaseUnit::Candela,
_ => { return None; }
};
let mut u = Unit::new();
u.insert(b, 1f64);
return Some(u);
}
} }