diff --git a/src/lib.rs b/src/lib.rs index 78d15b2d..738566cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ pub mod input; mod interrupt; mod memory_mapped; pub mod mgba; +pub mod number; mod single; pub mod syscall; diff --git a/src/number.rs b/src/number.rs new file mode 100644 index 00000000..3e411106 --- /dev/null +++ b/src/number.rs @@ -0,0 +1,86 @@ +use core::{ + fmt::Display, + ops::{Add, Div, Mul, Neg, Sub}, +}; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Num(i32); + +impl From for Num { + fn from(value: i32) -> Self { + Num(value << N) + } +} + +impl Add for Num { + type Output = Self; + fn add(self, rhs: Num) -> Self::Output { + Num(self.0 + rhs.0) + } +} + +impl Sub for Num { + type Output = Self; + fn sub(self, rhs: Num) -> Self::Output { + Num(self.0 - rhs.0) + } +} + +impl Mul for Num { + type Output = Self; + fn mul(self, rhs: Num) -> Self::Output { + if N % 2 == 0 { + Num((self.0 >> (N / 2)) * (rhs.0 >> (N / 2))) + } else { + Num((self.0 >> (1 + N / 2)) * (rhs.0 >> (N / 2))) + } + } +} + +impl Div for Num { + type Output = Self; + fn div(self, rhs: Num) -> Self::Output { + if N % 2 == 0 { + Num((self.0 << (N / 2)) / (rhs.0 >> (N / 2))) + } else { + Num((self.0 << (1 + N / 2)) / (rhs.0 >> (N / 2))) + } + } +} + +impl Neg for Num { + type Output = Self; + fn neg(self) -> Self::Output { + Num(-self.0) + } +} + +impl Num { + pub fn max() -> Self { + Num(i32::MAX) + } + pub fn min() -> Self { + Num(i32::MIN) + } +} + +impl Display for Num { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let integral = self.0 >> N; + let mask: u32 = (1 << N) - 1; + + write!(f, "{}", integral)?; + + let mut fractional = self.0 as u32 & mask; + if fractional & mask != 0 { + write!(f, ".")?; + } + while fractional & mask != 0 { + fractional *= 10; + write!(f, "{}", (fractional & !mask) >> N)?; + fractional &= mask; + } + + Ok(()) + } +}