Improved unit tostring

pull/2/head
Mark 2023-06-14 12:38:26 -07:00
parent 89c7d1d50b
commit f762817e4a
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 86 additions and 33 deletions

View File

@ -18,51 +18,104 @@ pub struct Unit {
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(); };
let mut top_empty = true;
let mut bottom_empty = true;
for (_, p) in self.get_val() { // Sort units by power
if p.is_positive() { let mut v: Vec<(&FreeUnit, &Scalar)> = self.get_val().iter().collect();
top_empty = false; v.sort_by(|a, b| b.1.partial_cmp(a.1).unwrap());
} else {
bottom_empty = false;
}
};
let mut i = v.iter();
let Some((mut u, mut p)) = i.next() else { panic!() };
let mut done = false;
// Positive powers
let mut t = String::new(); let mut t = String::new();
let mut b = String::new(); while p.is_positive() && !done {
for (u, p) in self.get_val() {
let c = u.to_string(); let c = u.to_string();
if *p == Scalar::new_rational(1f64).unwrap() { if *p == Scalar::new_rational(1f64).unwrap() {
t.push_str(&format!("{c}·")); t.push_str(&format!("{c}·"));
} else if *p == Scalar::new_rational(-1f64).unwrap() { } else if p.is_int() {
if top_empty { t.push_str(&c);
b.push_str(&format!("{c}⁻¹·")); for c in p.to_string().chars() {
} else { t.push( match c {
b.push_str(&format!("{c}·")); //'-' => '⁻',
'0' => '⁰',
'1' => '¹',
'2' => '²',
'3' => '³',
'4' => '⁴',
'5' => '⁵',
'6' => '⁶',
'7' => '⁷',
'8' => '⁸',
'9' => '⁹',
_ => panic!()
});
} }
} else if p.is_positive() { t.push('·');
} else {
t.push_str(&format!("{c}^{}·", p.to_string())); t.push_str(&format!("{c}^{}·", p.to_string()));
} else {
if top_empty {
b.push_str(&format!("{c}^{}·", p.to_string()));
} else {
b.push_str(&format!("{c}^{}·", (-p.clone()).to_string()));
}
} }
if let Some((a, b)) = i.next() {
u = a; p = b;
} else {done = true}
}; };
if top_empty { // Negative powers
format!("{}", &b[..b.len()-2]) // Slice cuts off the last `·` (2 bytes) let mut b = String::new();
} else if bottom_empty { let mut bottom_count = 0;
format!("{}", &t[..t.len()-2]) while !done {
} else { let c = u.to_string();
format!("{}/{}", &t[..t.len()-2], &b[..b.len()-2])
bottom_count += 1;
if t.len() != 0 && *p == Scalar::new_rational(-1f64).unwrap() {
b.push_str(&format!("{c}·"));
} else if p.is_int() {
b.push_str(&c);
for c in p.to_string().chars() {
if c == '-' && t.len() != 0 { continue; }
b.push( match c {
'-' => '⁻',
'0' => '⁰',
'1' => '¹',
'2' => '²',
'3' => '³',
'4' => '⁴',
'5' => '⁵',
'6' => '⁶',
'7' => '⁷',
'8' => '⁸',
'9' => '⁹',
_ => panic!()
});
} }
b.push('·');
} else {
b.push_str(&format!("{c}^{}·", p.to_string()));
}
if let Some((a, b)) = i.next() {
u = a; p = b;
} else {done = true}
};
// Slice cuts off the last `·` (2 bytes)
if t.len() == 0 {
return format!("{}", &b[..b.len() - 2]);
} else if b.len() == 0 {
return String::from(&t[..t.len() - 2]);
} else {
if bottom_count > 1 {
return format!("{}/({})", &t[..t.len() - 2], &b[..b.len() - 2] );
} else {
return format!("{}/{}", &t[..t.len() - 2], &b[..b.len() - 2] );
}
}
} }
} }

View File

@ -190,10 +190,10 @@ fn basic_units() {
good_expr("10 m", "10 * m"); good_expr("10 m", "10 * m");
good_expr("12 m", "(2 + 10) m"); good_expr("12 m", "(2 + 10) m");
good_expr("2 m^2", "2m^2"); good_expr("2 m²", "2m^2");
good_expr("4 m^2", "(2m)^2"); good_expr("4 m²", "(2m)^2");
good_expr("2 m^2", "2m * m"); good_expr("2 m²", "2m * m");
good_expr("1 m^2", "m m"); good_expr("1 m²", "m m");
good_expr("2 m", "rt (4m^2)"); good_expr("2 m", "rt (4m^2)");