From aa707df6c963dc1a88da78447af8e14adc7b931c Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 30 Jan 2019 17:31:24 +0100 Subject: [PATCH] constify some stuff --- src/display.rs | 14 ++++---- src/frac.rs | 1 + src/lib.rs | 83 +++++++++++++++++++++++---------------------- src/sealed_fixed.rs | 56 ++++++++++++------------------ src/sealed_float.rs | 10 +++--- src/sealed_int.rs | 74 +++++++++++++++++----------------------- 6 files changed, 108 insertions(+), 130 deletions(-) diff --git a/src/display.rs b/src/display.rs index 1af323d..add616d 100644 --- a/src/display.rs +++ b/src/display.rs @@ -82,7 +82,7 @@ macro_rules! fmt_radix2_helper { #[inline] fn take_frac_digit(&mut self, digit_bits: u32) -> u8 { - let nbits = <$UInner as SealedInt>::nbits(); + let nbits = <$UInner as SealedInt>::NBITS; let rem_bits = nbits - digit_bits; let mask = !0 << rem_bits; let ret = ((*self & mask) >> rem_bits) as u8; @@ -104,7 +104,7 @@ fn fmt_radix2_helper( where F: FmtRadix2Helper, { - let int_bits = F::nbits() - frac_bits; + let int_bits = F::NBITS - frac_bits; let digit_bits: u32 = radix.digit_bits(); // 128 binary digits, one radix point, one leading zero let mut buf: [u8; 130] = [0; 130]; @@ -150,7 +150,7 @@ where Bits: SealedInt, Bits::Unsigned: FmtRadix2Helper, { - fmt_radix2_helper(F::frac_bits(), num.parts(), radix, fmt) + fmt_radix2_helper(F::FRAC_NBITS, num.parts(), radix, fmt) } macro_rules! impl_fmt { @@ -252,7 +252,7 @@ macro_rules! fmt_dec_helper { impl FmtDecHelper for $UInner { #[inline] fn cmp_half(&self) -> Ordering { - self.cmp(&<$UInner as SealedInt>::msb()) + self.cmp(&<$UInner as SealedInt>::MSB) } #[inline] @@ -283,7 +283,7 @@ fn fmt_dec_helper( where F: FmtDecHelper, { - let int_bits = F::nbits() - frac_bits; + let int_bits = F::NBITS - frac_bits; // 40 int digits // + 128 frac digits // + 1 dec point, @@ -332,7 +332,7 @@ where *r = b'0' + frac.take_frac_digit(); } // check for rounding up - let round_up = match frac.cmp(&F::msb()) { + let round_up = match frac.cmp(&F::MSB) { Ordering::Less => false, Ordering::Greater => true, Ordering::Equal => { @@ -370,7 +370,7 @@ where Bits: SealedInt, Bits::Unsigned: FmtDecHelper, { - fmt_dec_helper(F::frac_bits(), num.parts(), fmt) + fmt_dec_helper(F::FRAC_NBITS, num.parts(), fmt) } #[cfg(test)] diff --git a/src/frac.rs b/src/frac.rs index 8beb487..e8b470c 100644 --- a/src/frac.rs +++ b/src/frac.rs @@ -19,6 +19,7 @@ This module reexports items from the [*typenum* crate]. [*typenum* crate]: https://crates.io/crates/typenum */ +pub(crate) use typenum::{Bit, False}; pub use typenum::{ IsGreaterOrEqual, IsLessOrEqual, True, Unsigned, U0, U1, U10, U100, U101, U102, U103, U104, U105, U106, U107, U108, U109, U11, U110, U111, U112, U113, U114, U115, U116, U117, U118, U119, diff --git a/src/lib.rs b/src/lib.rs index 006169f..04c5e04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -487,7 +487,7 @@ assert_eq!(Fix::int_bits(), ", ), #[inline] pub fn int_bits() -> u32 { - ::int_bits() + ::INT_NBITS } ); @@ -509,7 +509,7 @@ assert_eq!(Fix::frac_bits(), 6); ), #[inline] pub fn frac_bits() -> u32 { - ::frac_bits() + ::FRAC_NBITS } ); @@ -730,15 +730,12 @@ assert_eq!(Fix::saturating_from_fixed(too_small), Fix::min_value()); where F: Fixed, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); - let (value, overflow) = <::Bits as SealedInt>::to_fixed_overflow( val.to_bits(), - ::frac_bits(), - frac_bits, - int_bits, + F::FRAC_NBITS, + <$Fixed>::FRAC_NBITS, + <$Fixed>::FRAC_NBITS, ); if overflow { return if val.to_bits().neg_abs().0 { @@ -870,15 +867,12 @@ assert_eq!(Fix::overflowing_from_fixed(large), (wrapped, true)); where F: Fixed, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); - let (value, mut overflow) = <::Bits as SealedInt>::to_fixed_overflow( val.to_bits(), - ::frac_bits(), - frac_bits, - int_bits, + F::FRAC_NBITS, + <$Fixed>::FRAC_NBITS, + <$Fixed>::INT_NBITS, ); let bits = if_signed_unsigned!( $Signedness, @@ -1145,11 +1139,12 @@ assert_eq!(Fix::saturating_from_int(too_small), Fix::min_value()); where I: Int, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); - - let (value, overflow) = - ::to_fixed_overflow(val, 0, frac_bits, int_bits); + let (value, overflow) = ::to_fixed_overflow( + val, + 0, + <$Fixed>::FRAC_NBITS, + <$Fixed>::INT_NBITS, + ); if overflow { return if val.neg_abs().0 { $Fixed::min_value() @@ -1293,11 +1288,12 @@ assert_eq!(Fix::overflowing_from_int(large), (wrapped, true)); where I: Int, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); - - let (value, mut overflow) = - ::to_fixed_overflow(val, 0, frac_bits, int_bits); + let (value, mut overflow) = ::to_fixed_overflow( + val, + 0, + <$Fixed>::FRAC_NBITS, + <$Fixed>::INT_NBITS, + ); let bits = if_signed_unsigned!( $Signedness, match value { @@ -1359,8 +1355,8 @@ assert_eq!((-two_half).to_int(), -3);", #[inline] pub fn to_int(self) -> $Inner { let int = self.int().to_bits(); - if Self::frac_bits() < $nbits { - int >> Self::frac_bits() + if <$Fixed>::FRAC_NBITS < $nbits { + int >> <$Fixed>::FRAC_NBITS } else { int } @@ -1548,8 +1544,6 @@ assert_eq!(Fix::saturating_from_float(f64::NEG_INFINITY), Fix::min_value()); where F: Float, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); let saturated = if val.is_sign_positive() { $Fixed::max_value() } else { @@ -1558,19 +1552,22 @@ assert_eq!(Fix::saturating_from_float(f64::NEG_INFINITY), Fix::min_value()); if !val.is_finite() { return saturated; } - let (neg, abs_128, overflow) = - ::to_fixed_neg_abs_overflow(val, frac_bits, int_bits); + let (neg, abs_128, overflow) = ::to_fixed_neg_abs_overflow( + val, + <$Fixed>::FRAC_NBITS, + <$Fixed>::INT_NBITS, + ); if overflow { return saturated; } let abs_bits = abs_128 as <<$Fixed as SealedFixed>::Bits as SealedInt>::Unsigned; - if <<$Fixed as SealedFixed>::Bits as SealedInt>::is_signed() { + if <<$Fixed as SealedFixed>::Bits as SealedInt>::IS_SIGNED { // most significant bit (msb) can be one only for min value, // that is for a negative value with only the msb true. let msb = - <<$Fixed as SealedFixed>::Bits as SealedInt>::Unsigned::msb(); + <<$Fixed as SealedFixed>::Bits as SealedInt>::Unsigned::MSB; if abs_bits & msb != 0 { if !neg || abs_bits != msb { return saturated; @@ -1710,22 +1707,23 @@ assert_eq!(Fix::overflowing_from_float(large), (wrapped, true)); where F: Float, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); - if !val.is_finite() { panic!("{} is not finite", val); } let (neg, abs_128, mut overflow) = - ::to_fixed_neg_abs_overflow(val, frac_bits, int_bits); + ::to_fixed_neg_abs_overflow( + val, + <$Fixed>::FRAC_NBITS, + <$Fixed>::INT_NBITS, + ); let abs_bits = abs_128 as <<$Fixed as SealedFixed>::Bits as SealedInt>::Unsigned; - if <<$Fixed as SealedFixed>::Bits as SealedInt>::is_signed() { + if <<$Fixed as SealedFixed>::Bits as SealedInt>::IS_SIGNED { // most significant bit (msb) can be one only for min value, // that is for a negative value with only the msb true. let msb = - <<$Fixed as SealedFixed>::Bits as SealedInt>::Unsigned::msb(); + <<$Fixed as SealedFixed>::Bits as SealedInt>::Unsigned::MSB; if abs_bits & msb != 0 { if !neg || abs_bits != msb { overflow = true; @@ -1782,10 +1780,13 @@ assert_eq!(Fix::from_bits(", where F: Float, { - let frac_bits = Self::frac_bits(); - let int_bits = Self::int_bits(); let (neg, abs) = self.to_bits().neg_abs(); - SealedFloat::from_neg_abs(neg, u128::from(abs), frac_bits, int_bits) + SealedFloat::from_neg_abs( + neg, + u128::from(abs), + <$Fixed>::FRAC_NBITS, + <$Fixed>::INT_NBITS, + ) } ); diff --git a/src/sealed_fixed.rs b/src/sealed_fixed.rs index 31e041f..6f861cb 100644 --- a/src/sealed_fixed.rs +++ b/src/sealed_fixed.rs @@ -29,13 +29,18 @@ pub enum Widest { } pub trait SealedFixed: Copy + Debug + Display { + type FracNBits: Unsigned; type Bits: SealedInt; - type Frac: Unsigned; - fn frac_bits() -> u32; - fn int_bits() -> u32 { - Self::Bits::nbits() - Self::frac_bits() - } + const FRAC_NBITS: u32 = Self::FracNBits::U32; + const INT_NBITS: u32 = Self::Bits::NBITS - Self::FRAC_NBITS; + + const FRAC_MASK: u128 = !Self::INT_MASK; + // split shift in two parts in case that FRAC_NBITS == 128 + const INT_MASK: u128 = + !0 << (Self::FRAC_NBITS / 2) << (Self::FRAC_NBITS - Self::FRAC_NBITS / 2); + const FRAC_HI: u128 = Self::FRAC_MASK ^ (Self::FRAC_MASK >> 1); + const INT_LO: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1); fn from_fixed(fixed: F) -> Self where @@ -43,20 +48,20 @@ pub trait SealedFixed: Copy + Debug + Display { #[inline] fn one() -> Option { - let min_int_bits = if Self::Bits::is_signed() { 2 } else { 1 }; - if Self::int_bits() < min_int_bits { + let min_int_bits = if Self::Bits::IS_SIGNED { 2 } else { 1 }; + if Self::INT_NBITS < min_int_bits { None } else { - Some(Self::from_bits(Self::Bits::one_shl(Self::frac_bits()))) + Some(Self::from_bits(Self::Bits::one_shl(Self::FRAC_NBITS))) } } #[inline] fn minus_one() -> Option { - if !Self::Bits::is_signed() || Self::int_bits() < 1 { + if !Self::Bits::IS_SIGNED || Self::INT_NBITS < 1 { None } else { - Some(Self::from_bits(Self::Bits::all_ones_shl(Self::frac_bits()))) + Some(Self::from_bits(Self::Bits::all_ones_shl(Self::FRAC_NBITS))) } } @@ -84,13 +89,8 @@ macro_rules! sealed_fixed { where Frac: Unsigned + IsLessOrEqual<$Len, Output = True>, { + type FracNBits = Frac; type Bits = $Bits; - type Frac = Frac; - - #[inline] - fn frac_bits() -> u32 { - Frac::to_u32() - } #[inline] fn from_fixed(fixed: F) -> Self @@ -102,34 +102,22 @@ macro_rules! sealed_fixed { #[inline] fn frac_mask() -> Self::Bits { - !Self::int_mask() + Self::FRAC_MASK as _ } #[inline] fn int_mask() -> Self::Bits { - if Self::int_bits() == 0 { - 0 - } else { - !0 << Self::frac_bits() - } + Self::INT_MASK as _ } #[inline] fn highest_frac_bit() -> Self::Bits { - if Self::frac_bits() == 0 { - 0 - } else { - 1 << (Self::frac_bits() - 1) - } + Self::FRAC_HI as _ } #[inline] fn lowest_int_bit() -> Self::Bits { - if Self::int_bits() == 0 { - 0 - } else { - 1 << Self::frac_bits() - } + Self::INT_LO as _ } #[inline] @@ -150,8 +138,8 @@ macro_rules! sealed_fixed { ::Unsigned, ::Unsigned, ) { - let frac_bits = ::frac_bits(); - let int_bits = ::int_bits(); + let frac_bits = ::FRAC_NBITS; + let int_bits = ::INT_NBITS; let (neg, abs) = SealedInt::neg_abs(self.to_bits()); let (int_abs, frac_abs) = if int_bits == 0 { diff --git a/src/sealed_float.rs b/src/sealed_float.rs index 95753e8..f70c225 100644 --- a/src/sealed_float.rs +++ b/src/sealed_float.rs @@ -25,7 +25,7 @@ pub trait SealedFloat: Copy + Debug + Display { #[inline] fn exp_bias() -> i32 { - let nbits = Self::Bits::nbits(); + let nbits = Self::Bits::NBITS; let exp_bits = nbits - Self::prec(); (1 << (exp_bits - 1)) - 1 } @@ -64,7 +64,7 @@ macro_rules! sealed_float { #[inline] fn zero(neg: bool) -> $Float { - let nbits = ::nbits(); + let nbits = ::NBITS; let neg_mask = !0 << (nbits - 1); let neg_bits = if neg { neg_mask } else { 0 }; <$Float>::from_bits(neg_bits) @@ -72,7 +72,7 @@ macro_rules! sealed_float { #[inline] fn infinity(neg: bool) -> $Float { - let nbits = ::nbits(); + let nbits = ::NBITS; let neg_mask = !0 << (nbits - 1); let mant_mask = !(!0 << ($prec - 1)); let exp_mask = !(neg_mask | mant_mask); @@ -93,7 +93,7 @@ macro_rules! sealed_float { #[inline] fn parts(self) -> (bool, i32, $Bits) { - let nbits = ::nbits(); + let nbits = ::NBITS; let neg_mask = !0 << (nbits - 1); let mant_mask = !(!0 << ($prec - 1)); let exp_mask = !(neg_mask | mant_mask); @@ -175,7 +175,7 @@ macro_rules! sealed_float { frac_bits: u32, int_bits: u32, ) -> (bool, u128, bool) { - let float_bits = Self::Bits::nbits() as i32; + let float_bits = Self::Bits::NBITS as i32; let prec = Self::prec() as i32; let fix_bits = (frac_bits + int_bits) as i32; diff --git a/src/sealed_int.rs b/src/sealed_int.rs index 4c4e5f6..9689676 100644 --- a/src/sealed_int.rs +++ b/src/sealed_int.rs @@ -14,13 +14,18 @@ // . use core::fmt::{Debug, Display}; +use frac::{Bit, False, True, Unsigned, U1, U128, U16, U32, U64, U8}; use sealed_fixed::Widest; pub trait SealedInt: Copy + Ord + Debug + Display { + type NBits: Unsigned; + type IsSigned: Bit; type Unsigned: SealedInt; - fn is_signed() -> bool; - fn nbits() -> u32; + const NBITS: u32 = Self::NBits::U32; + const IS_SIGNED: bool = Self::IsSigned::BOOL; + const MSB: Self; + fn one_shl(shift: u32) -> Self; fn all_ones_shl(shift: u32) -> Self; fn is_zero(self) -> bool; @@ -34,27 +39,16 @@ pub trait SealedInt: Copy + Ord + Debug + Display { fn neg_abs(self) -> (bool, Self::Unsigned); fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self; - - #[inline] - fn msb() -> Self { - Self::one_shl(Self::nbits() - 1) - } } macro_rules! sealed_int { - ($Int:ident($Unsigned:ty, $is_signed:ident, $nbits:expr); $($rest:tt)*) => { + ($Int:ident($NBits:ident, $IsSigned:ident, $Unsigned:ty); $($rest:tt)*) => { impl SealedInt for $Int { + type NBits = $NBits; + type IsSigned = $IsSigned; type Unsigned = $Unsigned; - #[inline] - fn is_signed() -> bool { - $is_signed - } - - #[inline] - fn nbits() -> u32 { - $nbits - } + const MSB: $Int = 1 << (Self::NBITS - 1); #[inline] fn one_shl(shift: u32) -> $Int { @@ -74,9 +68,9 @@ macro_rules! sealed_int { $($rest)* } }; - ($Int:ident($Unsigned:ty, false, $nbits:expr)) => { + ($Unsigned:ident($NBits:ident)) => { sealed_int! { - $Int($Unsigned, false, $nbits); + $Unsigned($NBits, False, $Unsigned); #[inline] fn neg_abs(self) -> (bool, Self::Unsigned) { @@ -97,7 +91,7 @@ macro_rules! sealed_int { dst_frac_bits: u32, dst_int_bits: u32, ) -> (Widest, bool) { - let src_bits = ::nbits() as i32; + let src_bits = ::NBITS as i32; let dst_bits = (dst_frac_bits + dst_int_bits) as i32; if self == 0 { @@ -122,9 +116,9 @@ macro_rules! sealed_int { } } }; - ($Int:ident($Unsigned:ty, true, $nbits:expr)) => { + ($Signed:ident($NBits:ident, $Unsigned:ty)) => { sealed_int! { - $Int($Unsigned, true, $nbits); + $Signed($NBits, True, $Unsigned); #[inline] fn neg_abs(self) -> (bool, Self::Unsigned) { @@ -137,7 +131,7 @@ macro_rules! sealed_int { #[inline] fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self { - debug_assert!(abs <= Self::Unsigned::msb()); + debug_assert!(abs <= Self::Unsigned::MSB); if neg { abs.wrapping_neg() as Self } else { @@ -152,7 +146,7 @@ macro_rules! sealed_int { dst_frac_bits: u32, dst_int_bits: u32, ) -> (Widest, bool) { - let src_bits = ::nbits() as i32; + let src_bits = ::NBITS as i32; let dst_bits = (dst_frac_bits + dst_int_bits) as i32; if self >= 0 { @@ -185,17 +179,11 @@ macro_rules! sealed_int { } impl SealedInt for bool { + type NBits = U1; + type IsSigned = False; type Unsigned = bool; - #[inline] - fn is_signed() -> bool { - false - } - - #[inline] - fn nbits() -> u32 { - 1 - } + const MSB: bool = true; #[inline] fn one_shl(shift: u32) -> bool { @@ -252,13 +240,13 @@ impl SealedInt for bool { } } -sealed_int! { i8(u8, true, 8) } -sealed_int! { i16(u16, true, 16) } -sealed_int! { i32(u32, true, 32) } -sealed_int! { i64(u64, true, 64) } -sealed_int! { i128(u128, true, 128) } -sealed_int! { u8(u8, false, 8) } -sealed_int! { u16(u16, false, 16) } -sealed_int! { u32(u32, false, 32) } -sealed_int! { u64(u64, false, 64) } -sealed_int! { u128(u128, false, 128) } +sealed_int! { i8(U8, u8) } +sealed_int! { i16(U16, u16) } +sealed_int! { i32(U32, u32) } +sealed_int! { i64(U64, u64) } +sealed_int! { i128(U128, u128) } +sealed_int! { u8(U8) } +sealed_int! { u16(U16) } +sealed_int! { u32(U32) } +sealed_int! { u64(U64) } +sealed_int! { u128(U128) }