From 2df47cf5e375c73917ebcd6690cd16199d57af83 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Tue, 28 May 2024 18:12:02 -0700 Subject: Use num crate. --- src/eval.rs | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 +- src/num.rs | 198 ---------------------------------------------------------- src/parser.rs | 18 +++--- 4 files changed, 206 insertions(+), 208 deletions(-) create mode 100644 src/eval.rs delete mode 100644 src/num.rs (limited to 'src') diff --git a/src/eval.rs b/src/eval.rs new file mode 100644 index 0000000..d3b5ddc --- /dev/null +++ b/src/eval.rs @@ -0,0 +1,196 @@ +use num::pow::Pow; +use num::{BigInt, FromPrimitive, Signed, ToPrimitive}; +use std::fmt::{Display, Formatter}; + +pub enum Num { + Int(BigInt), + Float(f64), +} + +pub fn int(i: BigInt) -> Num { + Num::Int(i) +} + +pub fn float(f: f64) -> Num { + Num::Float(f) +} + +fn float_from_int(i: &BigInt) -> f64 { + if let Some(f) = i.to_f64() { + return f; + } + if i > &BigInt::ZERO { + std::f64::INFINITY + } else { + std::f64::NEG_INFINITY + } +} + +impl Num { + fn as_float(&self) -> f64 { + match self { + Num::Int(i) => float_from_int(i), + Num::Float(f) => *f, + } + } + + pub fn pow(self, other: Num) -> Num { + match (self, other) { + (Num::Int(i1), Num::Int(i2)) => { + if i2 < BigInt::ZERO { + return float(float_from_int(&i1).powf(float_from_int(&i2))); + } + let (_, u2) = i2.into_parts(); + int(i1.pow(u2)) + } + (n1, n2) => float(n1.as_float().powf(n2.as_float())), + } + } + + pub fn mul(self, other: Num) -> Num { + match (self, other) { + (Num::Int(i1), Num::Int(i2)) => int(i1 * i2), + (n1, n2) => float(n1.as_float() * n2.as_float()), + } + } + + pub fn div(self, other: Num) -> Num { + float(self.as_float() / other.as_float()) + } + + pub fn int_div(self, other: Num) -> Num { + match (self, other) { + (Num::Int(i1), Num::Int(i2)) => int(i1 / i2), + (Num::Float(f1), Num::Float(f2)) => { + let r = f1 / f2; + if let Some(i) = BigInt::from_f64(r) { + return int(i); + } + float(r) + } + (Num::Int(i), Num::Float(f)) => { + if let Some(fi) = BigInt::from_f64(f) { + return int(i / fi); + } + float(float_from_int(&i) / f) + } + (Num::Float(f), Num::Int(i)) => { + if let Some(fi) = BigInt::from_f64(f) { + return int(fi / i); + } + float(f / float_from_int(&i)) + } + } + } + + pub fn add(self, other: Num) -> Num { + match (self, other) { + (Num::Int(i1), Num::Int(i2)) => int(i1 + i2), + (n1, n2) => float(n1.as_float() + n2.as_float()), + } + } + + pub fn sub(self, other: Num) -> Num { + match (self, other) { + (Num::Int(i1), Num::Int(i2)) => int(i1 - i2), + (n1, n2) => Num::Float(n1.as_float() - n2.as_float()), + } + } + + pub fn sin(self) -> Num { + float(self.as_float().sin()) + } + + pub fn cos(self) -> Num { + float(self.as_float().cos()) + } + + pub fn tan(self) -> Num { + float(self.as_float().tan()) + } + + pub fn sqrt(self) -> Num { + match self { + Num::Int(i) if i >= BigInt::ZERO => { + let s = i.sqrt(); + if i != &s * &s { + return float(float_from_int(&i).sqrt()); + } + int(s) + } + n => float(n.as_float().sqrt()), + } + } + + pub fn log(self) -> Num { + float(self.as_float().ln()) + } + + pub fn log10(self) -> Num { + float(self.as_float().log10()) + } + + pub fn log2(self) -> Num { + float(self.as_float().log2()) + } + + pub fn floor(self) -> Num { + match self { + Num::Int(i) => int(i), + Num::Float(f) => { + if let Some(i) = BigInt::from_f64(f.floor()) { + return int(i); + } + float(f) + } + } + } + + pub fn ceil(self) -> Num { + match self { + Num::Int(i) => int(i), + Num::Float(f) => { + if let Some(i) = BigInt::from_f64(f.ceil()) { + return int(i); + } + float(f) + } + } + } + + pub fn round(self) -> Num { + match self { + Num::Int(i) => int(i), + Num::Float(f) => { + if let Some(i) = BigInt::from_f64(f.round_ties_even()) { + return int(i); + } + float(f) + } + } + } + + pub fn abs(self) -> Num { + match self { + Num::Int(i) => int(i.abs()), + Num::Float(f) => float(f.abs()), + } + } +} + +fn format_float(f: f64) -> String { + let mut s = format!("{f:.7}"); + while let Some(b'0') = s.as_bytes().get(s.len() - 1) { + s.truncate(s.len() - 1); + } + s +} + +impl Display for Num { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + match self { + Num::Int(n) => write!(f, "{n}"), + Num::Float(n) => write!(f, "{}", format_float(*n)), + } + } +} diff --git a/src/main.rs b/src/main.rs index e505ee6..08c1ded 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ +mod eval; mod lexer; -mod num; mod parser; use gdk4::{Key, ModifierType}; diff --git a/src/num.rs b/src/num.rs deleted file mode 100644 index 10dfea2..0000000 --- a/src/num.rs +++ /dev/null @@ -1,198 +0,0 @@ -use num_bigint::BigInt; -use num_traits::cast::ToPrimitive; -use num_traits::pow::Pow; -use num_traits::{FromPrimitive, Signed}; -use std::fmt::{Display, Formatter}; - -pub enum Num { - Int(BigInt), - Float(f64), -} - -pub fn int(i: BigInt) -> Num { - Num::Int(i) -} - -pub fn float(f: f64) -> Num { - Num::Float(f) -} - -fn float_from_int(i: &BigInt) -> f64 { - if let Some(f) = i.to_f64() { - return f; - } - if i > &BigInt::ZERO { - std::f64::INFINITY - } else { - std::f64::NEG_INFINITY - } -} - -impl Num { - fn as_float(&self) -> f64 { - match self { - Num::Int(i) => float_from_int(i), - Num::Float(f) => *f, - } - } - - pub fn pow(self, other: Num) -> Num { - match (self, other) { - (Num::Int(i1), Num::Int(i2)) => { - if i2 < BigInt::ZERO { - return float(float_from_int(&i1).powf(float_from_int(&i2))); - } - let (_, u2) = i2.into_parts(); - int(i1.pow(u2)) - } - (n1, n2) => float(n1.as_float().powf(n2.as_float())), - } - } - - pub fn mul(self, other: Num) -> Num { - match (self, other) { - (Num::Int(i1), Num::Int(i2)) => int(i1 * i2), - (n1, n2) => float(n1.as_float() * n2.as_float()), - } - } - - pub fn div(self, other: Num) -> Num { - float(self.as_float() / other.as_float()) - } - - pub fn int_div(self, other: Num) -> Num { - match (self, other) { - (Num::Int(i1), Num::Int(i2)) => int(i1 / i2), - (Num::Float(f1), Num::Float(f2)) => { - let r = f1 / f2; - if let Some(i) = BigInt::from_f64(r) { - return int(i); - } - float(r) - } - (Num::Int(i), Num::Float(f)) => { - if let Some(fi) = BigInt::from_f64(f) { - return int(i / fi); - } - float(float_from_int(&i) / f) - } - (Num::Float(f), Num::Int(i)) => { - if let Some(fi) = BigInt::from_f64(f) { - return int(fi / i); - } - float(f / float_from_int(&i)) - } - } - } - - pub fn add(self, other: Num) -> Num { - match (self, other) { - (Num::Int(i1), Num::Int(i2)) => int(i1 + i2), - (n1, n2) => float(n1.as_float() + n2.as_float()), - } - } - - pub fn sub(self, other: Num) -> Num { - match (self, other) { - (Num::Int(i1), Num::Int(i2)) => int(i1 - i2), - (n1, n2) => Num::Float(n1.as_float() - n2.as_float()), - } - } - - pub fn sin(self) -> Num { - float(self.as_float().sin()) - } - - pub fn cos(self) -> Num { - float(self.as_float().cos()) - } - - pub fn tan(self) -> Num { - float(self.as_float().tan()) - } - - pub fn sqrt(self) -> Num { - match self { - Num::Int(i) if i >= BigInt::ZERO => { - let s = i.sqrt(); - if i != &s * &s { - return float(float_from_int(&i).sqrt()); - } - int(s) - } - n => float(n.as_float().sqrt()), - } - } - - pub fn log(self) -> Num { - float(self.as_float().ln()) - } - - pub fn log10(self) -> Num { - float(self.as_float().log10()) - } - - pub fn log2(self) -> Num { - float(self.as_float().log2()) - } - - pub fn floor(self) -> Num { - match self { - Num::Int(i) => int(i), - Num::Float(f) => { - if let Some(i) = BigInt::from_f64(f.floor()) { - return int(i); - } - float(f) - } - } - } - - pub fn ceil(self) -> Num { - match self { - Num::Int(i) => int(i), - Num::Float(f) => { - if let Some(i) = BigInt::from_f64(f.ceil()) { - return int(i); - } - float(f) - } - } - } - - pub fn round(self) -> Num { - match self { - Num::Int(i) => int(i), - Num::Float(f) => { - if let Some(i) = BigInt::from_f64(f.round_ties_even()) { - return int(i); - } - float(f) - } - } - } - - pub fn abs(self) -> Num { - match self { - Num::Int(i) => int(i.abs()), - Num::Float(f) => float(f.abs()), - } - } -} - -fn format_float(f: f64) -> String { - let mut s = format!("{f:.7}"); - while let Some(b'0') = s.as_bytes().get(s.len() - 1) { - s.truncate(s.len() - 1); - } - s -} - -impl Display for Num { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { - match self { - Num::Int(n) => write!(f, "{n}"), - Num::Float(n) => write!(f, "{}", format_float(*n)), - } - } -} diff --git a/src/parser.rs b/src/parser.rs index 01f0e1b..b391202 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,7 @@ +use crate::eval; +use crate::eval::Num; use crate::lexer::Lexer; -use crate::num; -use crate::num::Num; -use num_bigint::BigInt; +use num::BigInt; use std::str::FromStr; enum ParseError { @@ -70,17 +70,17 @@ impl<'a> Parser<'a> { return Err(ParseError::Consumed); }; if negative { - return Ok(num::float(-f)); + return Ok(eval::float(-f)); } - return Ok(num::float(f)); + return Ok(eval::float(f)); } let Ok(i) = BigInt::from_str(t) else { return Err(ParseError::Consumed); }; if negative { - return Ok(num::int(-i)); + return Ok(eval::int(-i)); } - Ok(num::int(i)) + Ok(eval::int(i)) } fn paren_expr(&mut self) -> Result { @@ -96,10 +96,10 @@ impl<'a> Parser<'a> { fn parse_const(&mut self) -> Result { if self.symbol("e") { - return Ok(num::float(std::f64::consts::E)); + return Ok(eval::float(std::f64::consts::E)); } if self.symbol("pi") { - return Ok(num::float(std::f64::consts::PI)); + return Ok(eval::float(std::f64::consts::PI)); } Err(ParseError::Empty) } -- cgit v1.3.1