diff --git a/src/cmp.rs b/src/cmp.rs index 697aaec..5de9512 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -18,7 +18,7 @@ use half::f16; use { crate::{ frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8}, - sealed::{SealedFixed, SealedFloat, SealedInt, Widest}, + sealed::{Fixed, SealedFixed, SealedFloat, SealedInt, Widest}, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64, FixedU8, }, @@ -40,8 +40,8 @@ macro_rules! fixed_cmp_fixed { Self::INT_NBITS, ); let rhs_bits = match rhs_128 { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as ::Bits, }; dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits() } @@ -72,8 +72,8 @@ macro_rules! fixed_cmp_fixed { }; } let rhs_bits = match rhs_128 { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as ::Bits, }; Some(self.to_bits().cmp(&rhs_bits).then(dir)) } @@ -94,8 +94,8 @@ macro_rules! fixed_cmp_fixed { return !rhs.to_bits().is_negative(); } let rhs_bits = match rhs_128 { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as ::Bits, }; self.to_bits() < rhs_bits || (self.to_bits() == rhs_bits && dir == Ordering::Less) } @@ -216,8 +216,8 @@ macro_rules! fixed_cmp_float { let (rhs_128, dir, overflow) = rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); let rhs_bits = match rhs_128 { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as ::Bits, }; dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits() } @@ -265,8 +265,8 @@ macro_rules! fixed_cmp_float { }; } let rhs_bits = match rhs_128 { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as ::Bits, }; Some(self.to_bits().cmp(&rhs_bits).then(dir)) } @@ -291,8 +291,8 @@ macro_rules! fixed_cmp_float { return !rhs_is_neg; } let rhs_bits = match rhs_128 { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as ::Bits, }; let lhs_bits = self.to_bits(); lhs_bits < rhs_bits || (lhs_bits == rhs_bits && dir == Ordering::Less) @@ -343,8 +343,8 @@ macro_rules! fixed_cmp_float { return lhs_is_neg; } let lhs_bits = match lhs_128 { - Widest::Unsigned(bits) => bits as <$Fix as SealedFixed>::Bits, - Widest::Negative(bits) => bits as <$Fix as SealedFixed>::Bits, + Widest::Unsigned(bits) => bits as <$Fix as Fixed>::Bits, + Widest::Negative(bits) => bits as <$Fix as Fixed>::Bits, }; let rhs_bits = rhs.to_bits(); lhs_bits < rhs_bits || (lhs_bits == rhs_bits && dir == Ordering::Greater) diff --git a/src/display.rs b/src/display.rs index ab4e0b0..ef6f3d5 100644 --- a/src/display.rs +++ b/src/display.rs @@ -148,7 +148,7 @@ where #[inline] fn fmt_radix2(num: F, radix: &dyn Radix2, fmt: &mut Formatter) -> FmtResult where - F: SealedFixed, + F: SealedFixed, Bits: SealedInt, Bits::Unsigned: FmtRadix2Helper, { @@ -368,7 +368,7 @@ where #[inline] fn fmt_dec(num: F, fmt: &mut Formatter) -> FmtResult where - F: SealedFixed, + F: SealedFixed, Bits: SealedInt, Bits::Unsigned: FmtDecHelper, { diff --git a/src/lib.rs b/src/lib.rs index 9be5f7f..9a1dd45 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -224,11 +224,12 @@ use { }, }; -/// A "prelude" for users of the *fixed* crate. +/// A prelude for users of the *fixed* crate. /// -/// This prelude is similar to the standard library's prelude in that you'll -/// almost always want to import its entire contents, but unlike the standard -/// library's prelude you'll have to do so manually: +/// This prelude is similar to the [standard library’s +/// prelude][prelude] in that you’ll almost always want to import its +/// entire contents, but unlike the standard library’s prelude you’ll +/// have to do so manually: /// /// ``` /// ##[allow(unused_imports)] @@ -236,8 +237,13 @@ use { /// ``` /// /// The prelude may grow over time as additional items see ubiquitous use. +/// +/// [prelude]: https://doc.rust-lang.org/nightly/std/prelude/index.html pub mod prelude { - pub use crate::traits::{FromFixed, ToFixed}; + pub use crate::{ + sealed::Fixed, + traits::{FromFixed, ToFixed}, + }; } #[macro_use] diff --git a/src/macros_round.rs b/src/macros_round.rs index 2f2a2c2..b215a31 100644 --- a/src/macros_round.rs +++ b/src/macros_round.rs @@ -56,7 +56,7 @@ assert_eq!((-two_and_quarter).int(), -three); "; #[inline] pub fn int(self) -> $Fixed { - let mask = Self::INT_MASK as ::Bits; + let mask = Self::INT_MASK as ::Bits; Self::from_bits(self.to_bits() & mask) } ); @@ -102,7 +102,7 @@ assert_eq!((-two_and_quarter).frac(), three_quarters); "; #[inline] pub fn frac(self) -> $Fixed { - let mask = Self::FRAC_MASK as ::Bits; + let mask = Self::FRAC_MASK as ::Bits; Self::from_bits(self.to_bits() & mask) } ); @@ -562,7 +562,7 @@ assert_eq!(two_half.overflowing_ceil(), (Fix::from_int(3), false)); if Self::INT_NBITS == 0 { return (int, self.to_bits() > 0); } - let int_lsb = Self::INT_LSB as ::Bits; + let int_lsb = Self::INT_LSB as ::Bits; let increment = Self::from_bits(int_lsb); if_signed! { $Signedness; @@ -652,11 +652,11 @@ assert_eq!(two_half.overflowing_round(), (Fix::from_int(3), false)); #[inline] pub fn overflowing_round(self) -> ($Fixed, bool) { let int = self.int(); - let frac_msb = Self::FRAC_MSB as ::Bits; + let frac_msb = Self::FRAC_MSB as ::Bits; if (self.to_bits() & frac_msb) == 0 { return (int, false); } - let int_lsb = Self::INT_LSB as ::Bits; + let int_lsb = Self::INT_LSB as ::Bits; let increment = Self::from_bits(int_lsb); if_signed! { $Signedness; diff --git a/src/sealed.rs b/src/sealed.rs index 0eea53a..84e06ec 100644 --- a/src/sealed.rs +++ b/src/sealed.rs @@ -50,7 +50,7 @@ use half::f16; /// [`u64`]: https://doc.rust-lang.org/nightly/std/primitive.u64.html /// [`u8`]: https://doc.rust-lang.org/nightly/std/primitive.u8.html /// [`usize`]: https://doc.rust-lang.org/nightly/std/primitive.usize.html -pub trait Int: SealedInt + FromFixed + ToFixed {} +pub trait Int: SealedInt + FromFixed + ToFixed + Copy {} /// This trait is implemented for the primitive floating-point types, /// and for [`f16`] if the [`f16` feature] is enabled. @@ -63,7 +63,7 @@ pub trait Int: SealedInt + FromFixed + ToFixed {} /// [`f32`]: https://doc.rust-lang.org/nightly/std/primitive.f32.html /// [`f64`]: https://doc.rust-lang.org/nightly/std/primitive.f64.html /// [`f16` feature]: ../index.html#optional-features -pub trait Float: SealedFloat + FromFixed + ToFixed {} +pub trait Float: SealedFloat + FromFixed + ToFixed + Copy {} /// This trait is implemented for all the fixed-point types. /// @@ -82,36 +82,16 @@ pub trait Float: SealedFloat + FromFixed + ToFixed {} /// [`FixedU32`]: ../struct.FixedU32.html /// [`FixedU64`]: ../struct.FixedU64.html /// [`FixedU8`]: ../struct.FixedU8.html -pub trait Fixed: SealedFixed + FromFixed + ToFixed {} +pub trait Fixed: SealedFixed + FromFixed + ToFixed + Copy { + /// The primitive integer underlying type. + type Bits: Int; -impl Int for i8 {} -impl Int for i16 {} -impl Int for i32 {} -impl Int for i64 {} -impl Int for i128 {} -impl Int for isize {} -impl Int for u8 {} -impl Int for u16 {} -impl Int for u32 {} -impl Int for u64 {} -impl Int for u128 {} -impl Int for usize {} + /// Create with a given bit representation. + fn from_bits(bits: Self::Bits) -> Self; -#[cfg(feature = "f16")] -impl Float for f16 {} -impl Float for f32 {} -impl Float for f64 {} - -impl Fixed for FixedI8 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedI16 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedI32 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedI64 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedI128 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedU8 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedU16 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedU32 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedU64 where Frac: Unsigned + IsLessOrEqual {} -impl Fixed for FixedU128 where Frac: Unsigned + IsLessOrEqual {} + /// Convert to a bit representation. + fn to_bits(self) -> Self::Bits; +} impl ToFixed for bool { #[inline] @@ -151,8 +131,10 @@ impl ToFixed for bool { } } -macro_rules! checked_int { - ($Int:ty) => { +macro_rules! impl_int { + ($Int:ident) => { + impl Int for $Int {} + impl FromFixed for $Int { #[inline] fn from_fixed(val: F) -> Self @@ -231,21 +213,23 @@ macro_rules! checked_int { }; } -checked_int! { i8 } -checked_int! { i16 } -checked_int! { i32 } -checked_int! { i64 } -checked_int! { i128 } -checked_int! { isize } -checked_int! { u8 } -checked_int! { u16 } -checked_int! { u32 } -checked_int! { u64 } -checked_int! { u128 } -checked_int! { usize } +impl_int! { i8 } +impl_int! { i16 } +impl_int! { i32 } +impl_int! { i64 } +impl_int! { i128 } +impl_int! { isize } +impl_int! { u8 } +impl_int! { u16 } +impl_int! { u32 } +impl_int! { u64 } +impl_int! { u128 } +impl_int! { usize } -macro_rules! checked_float { +macro_rules! impl_float { ($Float:ty) => { + impl Float for $Float {} + impl FromFixed for $Float { #[inline] fn from_fixed(val: F) -> Self @@ -325,12 +309,27 @@ macro_rules! checked_float { } #[cfg(feature = "f16")] -checked_float! { f16 } -checked_float! { f32 } -checked_float! { f64 } +impl_float! { f16 } +impl_float! { f32 } +impl_float! { f64 } + +macro_rules! impl_fixed { + ($Fixed:ident, $NBits:ident, $Bits:ident) => { + impl Fixed for $Fixed + where + Frac: Unsigned + IsLessOrEqual<$NBits, Output = True>, + { + type Bits = $Bits; + #[inline] + fn from_bits(bits: Self::Bits) -> Self { + $Fixed::from_bits(bits) + } + #[inline] + fn to_bits(self) -> Self::Bits { + self.to_bits() + } + } -macro_rules! checked_fixed { - ($Fixed:ident, $NBits:ident) => { impl FromFixed for $Fixed where Frac: Unsigned + IsLessOrEqual<$NBits, Output = True>, @@ -415,13 +414,13 @@ macro_rules! checked_fixed { }; } -checked_fixed! { FixedI8, U8 } -checked_fixed! { FixedI16, U16 } -checked_fixed! { FixedI32, U32 } -checked_fixed! { FixedI64, U64 } -checked_fixed! { FixedI128, U128 } -checked_fixed! { FixedU8, U8 } -checked_fixed! { FixedU16, U16 } -checked_fixed! { FixedU32, U32 } -checked_fixed! { FixedU64, U64 } -checked_fixed! { FixedU128, U128 } +impl_fixed! { FixedI8, U8, i8 } +impl_fixed! { FixedI16, U16, i16 } +impl_fixed! { FixedI32, U32, i32 } +impl_fixed! { FixedI64, U64, i64 } +impl_fixed! { FixedI128, U128, i128 } +impl_fixed! { FixedU8, U8, u8 } +impl_fixed! { FixedU16, U16, u16 } +impl_fixed! { FixedU32, U32, u32 } +impl_fixed! { FixedU64, U64, u64 } +impl_fixed! { FixedU128, U128, u128 } diff --git a/src/sealed_fixed.rs b/src/sealed_fixed.rs index fa9bb66..7e733f9 100644 --- a/src/sealed_fixed.rs +++ b/src/sealed_fixed.rs @@ -35,10 +35,10 @@ pub enum Widest { pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord { type FracNBits: Unsigned; - type Bits: SealedInt; + type SBits: SealedInt; const FRAC_NBITS: u32 = Self::FracNBits::U32; - const INT_NBITS: u32 = Self::Bits::NBITS - Self::FRAC_NBITS; + const INT_NBITS: u32 = Self::SBits::NBITS - Self::FRAC_NBITS; const FRAC_MASK: u128 = !Self::INT_MASK; // split shift in two parts in case that FRAC_NBITS == 128 @@ -96,31 +96,33 @@ pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord { #[inline] fn one() -> Option { - let min_int_bits = if Self::Bits::IS_SIGNED { 2 } else { 1 }; + let min_int_bits = if Self::SBits::IS_SIGNED { 2 } else { 1 }; if Self::INT_NBITS < min_int_bits { None } else { - Some(Self::from_bits(Self::Bits::one_shl(Self::FRAC_NBITS))) + Some(Self::from_sbits(Self::SBits::one_shl(Self::FRAC_NBITS))) } } #[inline] fn minus_one() -> Option { - if !Self::Bits::IS_SIGNED || Self::INT_NBITS < 1 { + if !Self::SBits::IS_SIGNED || Self::INT_NBITS < 1 { None } else { - Some(Self::from_bits(Self::Bits::all_ones_shl(Self::FRAC_NBITS))) + Some(Self::from_sbits(Self::SBits::all_ones_shl( + Self::FRAC_NBITS, + ))) } } - fn from_bits(bits: Self::Bits) -> Self; - fn to_bits(self) -> Self::Bits; + fn from_sbits(bits: Self::SBits) -> Self; + fn to_sbits(self) -> Self::SBits; fn parts( self, ) -> ( bool, - ::Unsigned, - ::Unsigned, + ::Unsigned, + ::Unsigned, ); fn wrapping_ceil(self) -> Self; @@ -137,7 +139,7 @@ macro_rules! sealed_fixed { Frac: Unsigned + IsLessOrEqual<$Len, Output = True>, { type FracNBits = Frac; - type Bits = $Bits; + type SBits = $Bits; #[inline] fn saturating_from_fixed(val: F) -> Self @@ -151,30 +153,30 @@ macro_rules! sealed_fixed { ); if overflow { return if val.to_bits().is_negative() { - Self::from_bits(Self::Bits::min_value()) + Fixed::from_bits(Self::SBits::min_value()) } else { - Self::from_bits(Self::Bits::max_value()) + Fixed::from_bits(Self::SBits::max_value()) }; } let bits = if_signed_unsigned!( $Signedness, match value { Widest::Unsigned(bits) => { - if (bits as Self::Bits) < 0 { - return Self::from_bits(Self::Bits::max_value()); + if (bits as Self::SBits) < 0 { + return Fixed::from_bits(Self::SBits::max_value()); } - bits as Self::Bits + bits as Self::SBits } - Widest::Negative(bits) => bits as Self::Bits, + Widest::Negative(bits) => bits as Self::SBits, }, match value { - Widest::Unsigned(bits) => bits as Self::Bits, + Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(_) => { - return Self::from_bits(Self::Bits::min_value()); + return Fixed::from_bits(Self::SBits::min_value()); } }, ); - SealedFixed::from_bits(bits) + Fixed::from_bits(bits) } #[inline] @@ -191,22 +193,22 @@ macro_rules! sealed_fixed { $Signedness, match value { Widest::Unsigned(bits) => { - if (bits as Self::Bits) < 0 { + if (bits as Self::SBits) < 0 { overflow = true; } - bits as Self::Bits + bits as Self::SBits } - Widest::Negative(bits) => bits as Self::Bits, + Widest::Negative(bits) => bits as Self::SBits, }, match value { - Widest::Unsigned(bits) => bits as Self::Bits, + Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(bits) => { overflow = true; - bits as Self::Bits + bits as Self::SBits } }, ); - (SealedFixed::from_bits(bits), overflow) + (Fixed::from_bits(bits), overflow) } #[inline] @@ -234,19 +236,19 @@ macro_rules! sealed_fixed { $Signedness, match value { Widest::Unsigned(bits) => { - if (bits as ::Bits) < 0 { + if (bits as Self::SBits) < 0 { return Self::max_value(); } - bits as ::Bits + bits as Self::SBits } - Widest::Negative(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as Self::SBits, }, match value { - Widest::Unsigned(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(_) => return Self::min_value(), }, ); - SealedFixed::from_bits(bits) + Fixed::from_bits(bits) } #[inline] fn overflowing_from_float(val: F) -> (Self, bool) @@ -262,22 +264,22 @@ macro_rules! sealed_fixed { $Signedness, match value { Widest::Unsigned(bits) => { - if (bits as ::Bits) < 0 { + if (bits as Self::SBits) < 0 { overflow = true; } - bits as ::Bits + bits as Self::SBits } - Widest::Negative(bits) => bits as ::Bits, + Widest::Negative(bits) => bits as Self::SBits, }, match value { - Widest::Unsigned(bits) => bits as ::Bits, + Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(bits) => { overflow = true; - bits as ::Bits + bits as Self::SBits } }, ); - (SealedFixed::from_bits(bits), overflow) + (Fixed::from_bits(bits), overflow) } #[inline] @@ -290,12 +292,12 @@ macro_rules! sealed_fixed { } #[inline] - fn from_bits(bits: Self::Bits) -> Self { + fn from_sbits(bits: Self::SBits) -> Self { $Fixed::from_bits(bits) } #[inline] - fn to_bits(self) -> Self::Bits { + fn to_sbits(self) -> Self::SBits { $Fixed::to_bits(self) } @@ -304,8 +306,8 @@ macro_rules! sealed_fixed { self, ) -> ( bool, - ::Unsigned, - ::Unsigned, + ::Unsigned, + ::Unsigned, ) { let (neg, abs) = SealedInt::neg_abs(self.to_bits()); let (int_abs, frac_abs) = if Self::INT_NBITS == 0 {