From 2ecf62e06e3940c4cd2ed5e544b39ab04e93838d Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 22 Oct 2022 20:12:49 -0600 Subject: [PATCH] i think the debug finally works right? --- examples/hello.rs | 13 +++++++++ src/fixed.rs | 67 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/examples/hello.rs b/examples/hello.rs index bdeace5..9a0a1e4 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -59,6 +59,19 @@ extern "C" fn main() -> ! { if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Debug) { writeln!(logger, "hello!").ok(); + + let fx_u: Fixed = + Fixed::::wrapping_from(7) + Fixed::::from_raw(12); + writeln!(logger, "fixed unsigned: {fx_u:?}").ok(); + + let fx_i1: Fixed = + Fixed::::wrapping_from(8) + Fixed::::from_raw(15); + writeln!(logger, "fixed signed positive: {fx_i1:?}").ok(); + + let fx_i2: Fixed = Fixed::::wrapping_from(0) + - Fixed::::wrapping_from(3) + - Fixed::::from_raw(17); + writeln!(logger, "fixed signed negative: {fx_i2:?}").ok(); } { diff --git a/src/fixed.rs b/src/fixed.rs index 9165b8a..4906e01 100644 --- a/src/fixed.rs +++ b/src/fixed.rs @@ -25,7 +25,7 @@ pub type i32fx8 = Fixed; /// should be *less than* the number of bits in the integer's type. Multiply /// and divide ops need to shift the value by `B`, and so if `B` is greater /// than or equal to the integer's size the op will panic. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct Fixed(I); @@ -205,7 +205,7 @@ impl_common_fixed_ops!(u16); impl_common_fixed_ops!(u32); macro_rules! impl_signed_fixed_ops { - ($t:ty) => { + ($t:ty, $unsigned:ty) => { impl Fixed<$t, B> { /// Negate. #[inline] @@ -214,6 +214,13 @@ macro_rules! impl_signed_fixed_ops { Self(-self.0) } + /// If the number is negative or not. + #[inline] + #[must_use] + pub const fn is_negative(self) -> bool { + self.0 < 0 + } + /// Multiply. #[inline] #[must_use] @@ -230,13 +237,41 @@ macro_rules! impl_signed_fixed_ops { let d = m / (rhs.0 as i32); Self(d as $t) } + + /// Fractional part of the value. + #[inline] + #[must_use] + pub const fn fract(self) -> Self { + let frac_mask = (<$unsigned>::MAX >> (<$t>::BITS - B)); + Self((self.0.unsigned_abs() & frac_mask) as $t) + } + + /// Whole part of the value. + #[inline] + #[must_use] + pub const fn trunc(self) -> Self { + Self(((self.0.unsigned_abs() >> B) << B) as $t) + } } impl_trait_op_unit!($t, Neg, neg); + impl core::fmt::Debug for Fixed<$t, B> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + let whole: $t = self.trunc().into_raw() >> B; + let fract: $t = self.fract().into_raw(); + let divisor: $t = 1 << B; + if self.is_negative() { + let whole = whole.unsigned_abs(); + write!(f, "-({whole}+{fract}/{divisor})") + } else { + write!(f, "{whole}+{fract}/{divisor}") + } + } + } }; } -impl_signed_fixed_ops!(i8); -impl_signed_fixed_ops!(i16); -impl_signed_fixed_ops!(i32); +impl_signed_fixed_ops!(i8, u8); +impl_signed_fixed_ops!(i16, u16); +impl_signed_fixed_ops!(i32, u32); macro_rules! impl_unsigned_fixed_ops { ($t:ty) => { @@ -257,6 +292,28 @@ macro_rules! impl_unsigned_fixed_ops { let d = m / (rhs.0 as u32); Self(d as $t) } + + /// Fractional part of the value. + #[inline] + #[must_use] + pub const fn fract(self) -> Self { + Self(self.0 & (<$t>::MAX >> (<$t>::BITS - B))) + } + + /// Whole part of the value. + #[inline] + #[must_use] + pub const fn trunc(self) -> Self { + Self(self.0 & (<$t>::MAX << B)) + } + } + impl core::fmt::Debug for Fixed<$t, B> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + let whole: $t = self.trunc().into_raw() >> B; + let fract: $t = self.fract().into_raw(); + let divisor: $t = 1 << B; + write!(f, "{whole}+{fract}/{divisor}") + } } }; }