mirror of
https://github.com/tiffany352/rink-rs
synced 2024-11-10 13:44:15 +00:00
Change Dim from usize to Rc<String>
This commit is contained in:
parent
4f7454209f
commit
e92464d8cd
2 changed files with 24 additions and 22 deletions
23
src/eval.rs
23
src/eval.rs
|
@ -6,6 +6,7 @@ use number::{Number, Unit};
|
|||
use date;
|
||||
use unit_defs::DatePattern;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Value {
|
||||
|
@ -15,7 +16,7 @@ pub enum Value {
|
|||
|
||||
/// The evaluation context that contains unit definitions.
|
||||
pub struct Context {
|
||||
pub dimensions: Vec<String>,
|
||||
pub dimensions: Vec<Rc<String>>,
|
||||
pub units: HashMap<String, Number>,
|
||||
pub aliases: HashMap<Unit, String>,
|
||||
pub prefixes: Vec<(String, Number)>,
|
||||
|
@ -124,9 +125,9 @@ impl Context {
|
|||
/// Given a unit name, returns its value if it exists. Supports SI
|
||||
/// prefixes, plurals, bare dimensions like length, and aliases.
|
||||
pub fn lookup(&self, name: &str) -> Option<Number> {
|
||||
for (i, ref k) in self.dimensions.iter().enumerate() {
|
||||
if name == *k {
|
||||
return Some(Number::one_unit(i))
|
||||
for k in &self.dimensions {
|
||||
if name == &***k {
|
||||
return Some(Number::one_unit(k.to_owned()))
|
||||
}
|
||||
}
|
||||
self.units.get(name).cloned().or_else(|| {
|
||||
|
@ -164,18 +165,18 @@ impl Context {
|
|||
} else {
|
||||
let mut frac = vec![];
|
||||
let mut found = false;
|
||||
for (&dim, &pow) in &value.1 {
|
||||
for (dim, &pow) in &value.1 {
|
||||
if pow < 0 {
|
||||
frac.push((dim, -pow));
|
||||
} else {
|
||||
found = true;
|
||||
let mut map = Unit::new();
|
||||
map.insert(dim, pow);
|
||||
map.insert(dim.clone(), pow);
|
||||
if let Some(name) = self.aliases.get(&map) {
|
||||
write!(buf, " {}", name).unwrap();
|
||||
} else {
|
||||
let mut map = Unit::new();
|
||||
map.insert(dim, 1);
|
||||
map.insert(dim.clone(), 1);
|
||||
write!(buf, " {}", self.aliases[&map]).unwrap();
|
||||
if pow != 1 {
|
||||
write!(buf, "^{}", pow).unwrap();
|
||||
|
@ -191,12 +192,12 @@ impl Context {
|
|||
}
|
||||
for (dim, pow) in frac {
|
||||
let mut map = Unit::new();
|
||||
map.insert(dim, pow);
|
||||
map.insert(dim.clone(), pow);
|
||||
if let Some(name) = self.aliases.get(&map) {
|
||||
write!(buf, " {}", name).unwrap();
|
||||
} else {
|
||||
let mut map = Unit::new();
|
||||
map.insert(dim, 1);
|
||||
map.insert(dim.clone(), 1);
|
||||
write!(buf, " {}", self.aliases[&map]).unwrap();
|
||||
if pow != 1 {
|
||||
write!(buf, "^{}", pow).unwrap();
|
||||
|
@ -441,10 +442,10 @@ impl Context {
|
|||
for (name, def) in defs.defs {
|
||||
match *def {
|
||||
Def::Dimension(ref dname) => {
|
||||
let i = ctx.dimensions.len();
|
||||
let dname = Rc::new(dname.clone());
|
||||
ctx.dimensions.push(dname.clone());
|
||||
let mut map = Unit::new();
|
||||
map.insert(i, 1);
|
||||
map.insert(dname, 1);
|
||||
ctx.aliases.insert(map, name.clone());
|
||||
},
|
||||
Def::Unit(ref expr) => match ctx.eval(expr) {
|
||||
|
|
|
@ -3,11 +3,12 @@ use gmp::mpz::Mpz;
|
|||
use std::collections::BTreeMap;
|
||||
use eval::Show;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Number type
|
||||
pub type Num = Mpq;
|
||||
/// A simple alias to add semantic meaning for when we pass around dimension IDs.
|
||||
pub type Dim = usize;
|
||||
pub type Dim = Rc<String>;
|
||||
/// Alias for the primary representation of dimensionality.
|
||||
pub type Unit = BTreeMap<Dim, i64>;
|
||||
|
||||
|
@ -170,14 +171,14 @@ impl Number {
|
|||
pub fn invert(&self) -> Number {
|
||||
Number(&one() / &self.0,
|
||||
self.1.iter()
|
||||
.map(|(&k, &power)| (k, -power))
|
||||
.map(|(k, &power)| (k.clone(), -power))
|
||||
.collect::<Unit>())
|
||||
}
|
||||
|
||||
/// Raises a value to a dimensionless integer power.
|
||||
pub fn powi(&self, exp: i32) -> Number {
|
||||
let unit = self.1.iter()
|
||||
.map(|(&k, &power)| (k, power * exp as i64))
|
||||
.map(|(k, &power)| (k.clone(), power * exp as i64))
|
||||
.collect::<Unit>();
|
||||
Number(pow(&self.0, exp), unit)
|
||||
}
|
||||
|
@ -186,11 +187,11 @@ impl Number {
|
|||
/// powers divisible by n.
|
||||
pub fn root(&self, exp: i32) -> Option<Number> {
|
||||
let mut res = Unit::new();
|
||||
for (&dim, &power) in &self.1 {
|
||||
for (dim, &power) in &self.1 {
|
||||
if power % exp as i64 != 0 {
|
||||
return None
|
||||
} else {
|
||||
res.insert(dim, power / exp as i64);
|
||||
res.insert(dim.clone(), power / exp as i64);
|
||||
}
|
||||
}
|
||||
Some(Number(root(&self.0, exp), res))
|
||||
|
@ -256,11 +257,11 @@ impl Show for Number {
|
|||
value.0.canonicalize();
|
||||
|
||||
write!(out, "{}", self.show_number_part()).unwrap();
|
||||
for (&dim, &exp) in &value.1 {
|
||||
for (dim, &exp) in &value.1 {
|
||||
if exp < 0 {
|
||||
frac.push((dim, exp));
|
||||
frac.push((dim.clone(), exp));
|
||||
} else {
|
||||
write!(out, " {}", context.dimensions[dim]).unwrap();
|
||||
write!(out, " {}", dim).unwrap();
|
||||
if exp != 1 {
|
||||
write!(out, "^{}", exp).unwrap();
|
||||
}
|
||||
|
@ -270,7 +271,7 @@ impl Show for Number {
|
|||
write!(out, " /").unwrap();
|
||||
for (dim, exp) in frac {
|
||||
let exp = -exp;
|
||||
write!(out, " {}", context.dimensions[dim]).unwrap();
|
||||
write!(out, " {}", dim).unwrap();
|
||||
if exp != 1 {
|
||||
write!(out, "^{}", exp).unwrap();
|
||||
}
|
||||
|
@ -279,9 +280,9 @@ impl Show for Number {
|
|||
let alias = context.aliases.get(&value.1).cloned().or_else(|| {
|
||||
if value.1.len() == 1 {
|
||||
let e = value.1.iter().next().unwrap();
|
||||
let ref n = context.dimensions[*e.0];
|
||||
let ref n = *e.0;
|
||||
if *e.1 == 1 {
|
||||
Some(n.clone())
|
||||
Some((**n).clone())
|
||||
} else {
|
||||
Some(format!("{}^{}", n, e.1))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue