From e9645208d99091434c3f07e47842b421cc3bcc40 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 9 Apr 2023 08:39:22 -0700 Subject: [PATCH] Improved unit printing --- src/quantity/quantity.rs | 15 ++++++++------- src/quantity/scalar/f64base.rs | 1 + src/quantity/scalar/floatbase.rs | 1 + src/quantity/scalar/mod.rs | 8 ++++++++ src/quantity/scalar/rationalbase.rs | 1 + src/tokens/operator.rs | 29 +++++++++++++++++++++++++++-- 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/quantity/quantity.rs b/src/quantity/quantity.rs index 90e3d7e..a4e0f14 100644 --- a/src/quantity/quantity.rs +++ b/src/quantity/quantity.rs @@ -25,12 +25,13 @@ pub struct Quantity { impl ToString for Quantity { fn to_string(&self) -> String { - let mut n = self.v.to_string(); + let n = self.v.to_string(); if self.unitless() { return n; } - n.push(' '); - n.push_str(&self.u.to_string()); - return n; + let u = self.u.to_string(); + if self.is_one() { return u; }; + + return format!("{n} {u}"); } } @@ -75,9 +76,8 @@ impl Quantity { }); } - pub fn add_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; } } @@ -96,6 +96,7 @@ macro_rules! quant_foward { impl Quantity { pub fn is_zero(&self) -> bool { self.v.is_zero() } + pub fn is_one(&self) -> bool { self.v.is_one() } pub fn is_nan(&self) -> bool { self.v.is_nan() } pub fn is_negative(&self) -> bool { self.v.is_negative() } pub fn is_positive(&self) -> bool { self.v.is_positive() } diff --git a/src/quantity/scalar/f64base.rs b/src/quantity/scalar/f64base.rs index f672214..d272bdf 100644 --- a/src/quantity/scalar/f64base.rs +++ b/src/quantity/scalar/f64base.rs @@ -48,6 +48,7 @@ impl ScalarBase for F64Base { foward!(fract); fn is_zero(&self) -> bool {self.val == 0f64} + fn is_one(&self) -> bool {self.val == 1f64} fn is_negative(&self) -> bool { self.val.is_sign_negative() } fn is_positive(&self) -> bool { self.val.is_sign_positive() } diff --git a/src/quantity/scalar/floatbase.rs b/src/quantity/scalar/floatbase.rs index cb31f84..c588dc5 100644 --- a/src/quantity/scalar/floatbase.rs +++ b/src/quantity/scalar/floatbase.rs @@ -123,6 +123,7 @@ impl ScalarBase for FloatBase { foward!(fract); fn is_zero(&self) -> bool {self.val.is_zero()} + fn is_one(&self) -> bool {self.val == Float::with_val(FLOAT_PRECISION, 1)} fn is_negative(&self) -> bool { self.val.is_sign_negative() } fn is_positive(&self) -> bool { self.val.is_sign_positive() } diff --git a/src/quantity/scalar/mod.rs b/src/quantity/scalar/mod.rs index 4092860..22b7e9a 100644 --- a/src/quantity/scalar/mod.rs +++ b/src/quantity/scalar/mod.rs @@ -24,6 +24,7 @@ pub trait ScalarBase: // Utility fn fract(&self) -> Option; fn is_zero(&self) -> bool; + fn is_one(&self) -> bool; fn is_negative(&self) -> bool; fn is_positive(&self) -> bool; @@ -163,6 +164,13 @@ impl Scalar { } } + pub fn is_one(&self) -> bool { + match self { + Scalar::Rational{v} => v.is_one(), + Scalar::Float{v} => v.is_one(), + } + } + pub fn is_negative(&self) -> bool { match self { Scalar::Rational{v} => v.is_negative(), diff --git a/src/quantity/scalar/rationalbase.rs b/src/quantity/scalar/rationalbase.rs index df9d102..7c41107 100644 --- a/src/quantity/scalar/rationalbase.rs +++ b/src/quantity/scalar/rationalbase.rs @@ -110,6 +110,7 @@ impl ScalarBase for RationalBase { } fn is_zero(&self) -> bool {self.val == Rational::from((0,1))} + fn is_one(&self) -> bool {self.val == Rational::from((1,1))} fn is_negative(&self) -> bool { self.val.clone().signum() == -1 } fn is_positive(&self) -> bool { self.val.clone().signum() == 1 } diff --git a/src/tokens/operator.rs b/src/tokens/operator.rs index 1af5879..fca87e7 100644 --- a/src/tokens/operator.rs +++ b/src/tokens/operator.rs @@ -161,9 +161,34 @@ impl Operator { let (b, div) = (b, div); if div { - return format!("{} ÷ {}", self.add_parens_to_arg_strict(a), self.add_parens_to_arg_strict(b)); + return format!("{} ÷ {}", + self.add_parens_to_arg_strict(a), + self.add_parens_to_arg_strict(b) + ); } else { - return format!("{} × {}", self.add_parens_to_arg_strict(a), self.add_parens_to_arg_strict(b)); + + // Ommit times sign when we have a number + // multiplied by a unit (like 10 m) + // Times sign should stay in all other cases. + let no_times = if let Token::Number(p) = b { + if let Token::Number(q) = a { + (!p.unitless() && p.is_one()) && + !(!q.unitless() && p.is_one()) + } else {false} + } else {false}; + + if no_times { + return format!("{} {}", + self.add_parens_to_arg_strict(a), + self.add_parens_to_arg_strict(b) + ); + } else { + return format!("{} × {}", + self.add_parens_to_arg_strict(a), + self.add_parens_to_arg_strict(b) + ); + } + } },