Change Dim from usize to Rc<String>

This commit is contained in:
Tiffany Bennett 2016-08-12 20:41:53 -04:00
parent 4f7454209f
commit e92464d8cd
2 changed files with 24 additions and 22 deletions

View file

@ -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) {

View file

@ -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))
}