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