diff --git a/src/value/number/integer.rs b/src/value/number/integer.rs new file mode 100644 index 0000000..56753d4 --- /dev/null +++ b/src/value/number/integer.rs @@ -0,0 +1,150 @@ +use std::fmt::{self, Display, UpperHex}; +use std::mem; +use std::ops::{Add, AddAssign}; + +use num_bigint::BigInt; +use num_traits::{Signed, ToPrimitive, Zero}; + +#[derive(Eq, PartialEq)] +pub(crate) enum Integer { + Machine(i64), + Big(BigInt), +} + +impl Integer { + pub fn abs(&self) -> Self { + match self { + Self::Machine(v) => Self::Machine(v.abs()), + Self::Big(v) => Self::Big(v.abs()), + } + } + + pub fn is_ten(&self) -> bool { + match self { + Self::Machine(10) => true, + Self::Machine(..) => false, + Self::Big(v) => v == &BigInt::from(10), + } + } +} + +impl Default for Integer { + fn default() -> Self { + Self::zero() + } +} + +impl UpperHex for Integer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Machine(v) => write!(f, "{:02X}", v), + Self::Big(v) => write!(f, "{:02X}", v), + } + } +} + +impl Add for Integer { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + match self { + Self::Machine(val1) => match rhs { + Self::Machine(val2) => match val1.checked_add(val2) { + Some(v) => Self::Machine(v), + None => Self::Big(BigInt::from(val1) + val2), + }, + Self::Big(val2) => Self::Big(BigInt::from(val1) + val2), + }, + Self::Big(val1) => match rhs { + Self::Big(val2) => Self::Big(val1 + val2), + Self::Machine(val2) => Self::Big(val1 + BigInt::from(val2)), + }, + } + } +} + +impl Add for Integer { + type Output = Self; + fn add(self, rhs: BigInt) -> Self::Output { + match self { + Self::Machine(v) => Self::Big(BigInt::from(v) + rhs), + Self::Big(v) => Self::Big(v + rhs), + } + } +} + +impl Add for Integer { + type Output = Self; + fn add(self, rhs: i32) -> Self::Output { + match self { + Self::Machine(v) => match v.checked_add(rhs as i64) { + Some(v) => Self::Machine(v), + None => Self::Big(BigInt::from(v) + rhs), + }, + Self::Big(v) => Self::Big(v + rhs), + } + } +} + +impl AddAssign for Integer { + fn add_assign(&mut self, rhs: i32) { + let tmp = mem::take(self); + *self = tmp + rhs; + } +} + +impl AddAssign for Integer { + fn add_assign(&mut self, rhs: Self) { + let tmp = mem::take(self); + *self = tmp + rhs; + } +} + +impl Zero for Integer { + fn zero() -> Self { + Self::Machine(0) + } + + fn is_zero(&self) -> bool { + match self { + Self::Machine(0) => true, + Self::Machine(..) => false, + Self::Big(v) => v.is_zero(), + } + } + + fn set_zero(&mut self) { + *self = Self::zero() + } +} + +impl Display for Integer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Machine(v) => write!(f, "{}", v), + Self::Big(v) => write!(f, "{}", v), + } + } +} + +impl ToPrimitive for Integer { + fn to_u8(&self) -> Option { + match self { + Self::Machine(v) => v.to_u8(), + Self::Big(v) => v.to_u8(), + } + } + + fn to_u64(&self) -> Option { + match self { + Self::Machine(v) => v.to_u64(), + Self::Big(v) => v.to_u64(), + } + } + + fn to_i64(&self) -> std::option::Option { + match self { + Self::Machine(v) => Some(*v), + Self::Big(v) => v.to_i64(), + } + } +} diff --git a/src/value/number.rs b/src/value/number/mod.rs similarity index 83% rename from src/value/number.rs rename to src/value/number/mod.rs index 9eaaf22..0f6dd12 100644 --- a/src/value/number.rs +++ b/src/value/number/mod.rs @@ -1,6 +1,6 @@ use std::cmp::Ordering; use std::convert::{From, TryFrom}; -use std::fmt::{self, Display, UpperHex, Write}; +use std::fmt::{self, Display, Write}; use std::mem; use std::ops::{ Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign, @@ -8,156 +8,14 @@ use std::ops::{ use num_bigint::BigInt; use num_rational::{BigRational, Rational64}; -use num_traits::{ - CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Num, One, Signed, ToPrimitive, Zero, -}; +use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Num, One, Signed, Zero}; + +use integer::Integer; + +mod integer; const PRECISION: usize = 10; -#[derive(Eq, PartialEq)] -pub(crate) enum Integer { - Machine(i64), - Big(BigInt), -} - -impl Default for Integer { - fn default() -> Self { - Self::zero() - } -} - -impl UpperHex for Integer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Machine(v) => write!(f, "{:02X}", v), - Self::Big(v) => write!(f, "{:02X}", v), - } - } -} - -impl Add for Integer { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - match self { - Self::Machine(val1) => match rhs { - Self::Machine(val2) => match val1.checked_add(val2) { - Some(v) => Self::Machine(v), - None => Self::Big(BigInt::from(val1) + val2), - }, - Self::Big(val2) => Self::Big(BigInt::from(val1) + val2), - }, - Self::Big(val1) => match rhs { - Self::Big(val2) => Self::Big(val1 + val2), - Self::Machine(val2) => Self::Big(val1 + BigInt::from(val2)), - }, - } - } -} - -impl Add for Integer { - type Output = Self; - fn add(self, rhs: BigInt) -> Self::Output { - match self { - Self::Machine(v) => Self::Big(BigInt::from(v) + rhs), - Self::Big(v) => Self::Big(v + rhs), - } - } -} - -impl Add for Integer { - type Output = Self; - fn add(self, rhs: i32) -> Self::Output { - match self { - Self::Machine(v) => match v.checked_add(rhs as i64) { - Some(v) => Self::Machine(v), - None => Self::Big(BigInt::from(v) + rhs), - }, - Self::Big(v) => Self::Big(v + rhs), - } - } -} - -impl AddAssign for Integer { - fn add_assign(&mut self, rhs: i32) { - let tmp = mem::take(self); - *self = tmp + rhs; - } -} - -impl AddAssign for Integer { - fn add_assign(&mut self, rhs: Self) { - let tmp = mem::take(self); - *self = tmp + rhs; - } -} - -impl Zero for Integer { - fn zero() -> Self { - Self::Machine(0) - } - - fn is_zero(&self) -> bool { - match self { - Self::Machine(0) => true, - Self::Machine(..) => false, - Self::Big(v) => v.is_zero(), - } - } - - fn set_zero(&mut self) { - *self = Self::zero() - } -} - -impl Integer { - fn abs(&self) -> Self { - match self { - Self::Machine(v) => Self::Machine(v.abs()), - Self::Big(v) => Self::Big(v.abs()), - } - } - - fn is_ten(&self) -> bool { - match self { - Self::Machine(10) => true, - Self::Machine(..) => false, - Self::Big(v) => v == &BigInt::from(10), - } - } -} - -impl Display for Integer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Machine(v) => write!(f, "{}", v), - Self::Big(v) => write!(f, "{}", v), - } - } -} - -impl ToPrimitive for Integer { - fn to_u8(&self) -> Option { - match self { - Self::Machine(v) => v.to_u8(), - Self::Big(v) => v.to_u8(), - } - } - - fn to_u64(&self) -> Option { - match self { - Self::Machine(v) => v.to_u64(), - Self::Big(v) => v.to_u64(), - } - } - - fn to_i64(&self) -> std::option::Option { - match self { - Self::Machine(v) => Some(*v), - Self::Big(v) => v.to_i64(), - } - } -} - #[derive(Clone, Eq, PartialEq, Ord)] pub(crate) enum Number { Machine(Rational64),