diff options
Diffstat (limited to 'src/num.rs')
| -rw-r--r-- | src/num.rs | 198 |
1 files changed, 0 insertions, 198 deletions
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)), - } - } -} |
