From 12a47df74e9d2e146c40fe0ad1cf803f09d0c01d Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Fri, 10 Aug 2018 14:43:10 +0200 Subject: [PATCH] add some more methods --- src/lib.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/traits.rs | 17 ++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 90f5104..3046b32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -470,6 +470,15 @@ macro_rules! fixed { <$Inner>::checked_shr(self.0, rhs).map($Fixed::from_bits) } + if_signed! { + $Signedness => + /// Checked absolute value. + #[inline] + pub fn checked_abs(self) -> Option<$Fixed> { + <$Inner>::checked_abs(self.0).map($Fixed::from_bits) + } + } + /// Saturating fixed-point addition. #[inline] pub fn saturating_add(self, rhs: $Fixed) -> $Fixed { @@ -548,6 +557,15 @@ macro_rules! fixed { $Fixed(<$Inner>::wrapping_shr(self.0, rhs)) } + if_signed! { + $Signedness => + /// Wrapping absolute value. + #[inline] + pub fn wrapping_abs(self) -> $Fixed { + $Fixed(<$Inner>::wrapping_abs(self.0)) + } + } + /// Overflowing negation. #[inline] pub fn overflowing_neg(self) -> ($Fixed, bool) { @@ -597,6 +615,61 @@ macro_rules! fixed { ($Fixed(ans), o) } + if_signed! { + $Signedness => + /// Overflowing absolute value. + #[inline] + pub fn overflowing_abs(self) -> ($Fixed, bool) { + let (ans, o) = <$Inner>::overflowing_abs(self.0); + ($Fixed(ans), o) + } + } + + if_unsigned! { + $Signedness => pass_method! { + "Returns `true` if the fixed-point number is \ + 2k for some k.", + $Fixed($Inner) => fn is_power_of_two(self) -> bool + } + } + + if_unsigned! { + $Signedness => pass_method! { + "Returns the smallest power of two ≥ `self`.", + $Fixed($Inner) => fn next_power_of_two(self) + } + } + + if_unsigned! { + $Signedness => + /// Returns the smallest power of two ≥ `self`, or `None` + /// if the next power of two is too large to represent. + #[inline] + pub fn checked_next_power_of_two(self) -> Option<$Fixed> { + <$Inner>::checked_next_power_of_two(self.0).map($Fixed::from_bits) + } + } + + if_signed! { + $Signedness => pass_method! { + "Returns the absolute value of two ≥ `self`.", + $Fixed($Inner) => fn abs(self) + } + } + + if_signed! { + $Signedness => + /// Returns a number representing the sign of `self`. + #[inline] + pub fn signum(self) -> $Fixed { + match self.0.cmp(&0) { + Ordering::Equal => $Fixed(0), + Ordering::Greater => <$Fixed as FixedNum>::one().expect("overflow"), + Ordering::Less => <$Fixed as FixedNum>::minus_one().expect("overflow"), + } + } + } + doc_comment! { concat!( "Creates a fixed-point number of type `", diff --git a/src/traits.rs b/src/traits.rs index 2af5c59..ef4b797 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -24,6 +24,7 @@ use { pub(crate) trait FixedNum: Copy { type Part; fn one() -> Option; + fn minus_one() -> Option; fn parts(self) -> (bool, Self::Part, Self::Part); #[inline(always)] fn int_bits() -> u32 { @@ -110,6 +111,11 @@ macro_rules! fixed_num_unsigned { } } + #[inline] + fn minus_one() -> Option { + None + } + #[inline] fn parts(self) -> (bool, $Part, $Part) { let bits = self.to_bits(); @@ -139,6 +145,17 @@ macro_rules! fixed_num_signed { } } + #[inline] + fn minus_one() -> Option { + let int_bits = <$Fixed as FixedNum>::int_bits(); + let frac_bits = <$Fixed as FixedNum>::frac_bits(); + if int_bits < 1 { + None + } else { + Some($Fixed::from_bits(!0 << frac_bits)) + } + } + #[inline] fn parts(self) -> (bool, $Part, $Part) { let bits = self.to_bits().wrapping_abs() as $Part;