use core::{ fmt::Display, ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}, }; #[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 AddAssign for Num { fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0 } } impl Sub for Num { type Output = Self; fn sub(self, rhs: Num) -> Self::Output { Num(self.0 - rhs.0) } } impl SubAssign for Num { fn sub_assign(&mut self, rhs: Self) { 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 MulAssign for Num { fn mul_assign(&mut self, rhs: Self) { if N % 2 == 0 { self.0 = (self.0 >> (N / 2)) * (rhs.0 >> (N / 2)) } else { self.0 = (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 DivAssign for Num { fn div_assign(&mut self, rhs: Self) { if N % 2 == 0 { self.0 = (self.0 << (N / 2)) / (rhs.0 >> (N / 2)) } else { self.0 = (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) } pub fn int(&self) -> i32 { self.0 >> N } pub fn new(integral: i32) -> Self { Self(integral << N) } } 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(()) } }