diff --git a/src/cmp.rs b/src/cmp.rs index d47ea79..b1605ba 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -29,16 +29,16 @@ macro_rules! fixed_cmp_fixed { impl PartialEq<$Rhs> for $Lhs { #[inline] fn eq(&self, rhs: &$Rhs) -> bool { - let (rhs_128, dir, overflow) = rhs.to_bits().to_fixed_dir_overflow( + let conv = rhs.to_bits().to_fixed_helper( <$Rhs>::FRAC_NBITS as i32, Self::FRAC_NBITS, Self::INT_NBITS, ); - let rhs_bits = match rhs_128 { + let rhs_bits = match conv.bits { Widest::Unsigned(bits) => bits as ::Bits, Widest::Negative(bits) => bits as ::Bits, }; - dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits() + conv.dir == Ordering::Equal && !conv.overflow && rhs_bits == self.to_bits() } } @@ -50,23 +50,23 @@ macro_rules! fixed_cmp_fixed { (true, false) => return Some(Ordering::Less), _ => {} } - let (rhs_128, dir, overflow) = rhs.to_bits().to_fixed_dir_overflow( + let conv = rhs.to_bits().to_fixed_helper( <$Rhs>::FRAC_NBITS as i32, Self::FRAC_NBITS, Self::INT_NBITS, ); - if overflow { + if conv.overflow { return if rhs.to_bits().is_negative() { Some(Ordering::Greater) } else { Some(Ordering::Less) }; } - let rhs_bits = match rhs_128 { + let rhs_bits = match conv.bits { Widest::Unsigned(bits) => bits as ::Bits, Widest::Negative(bits) => bits as ::Bits, }; - Some(self.to_bits().cmp(&rhs_bits).then(dir)) + Some(self.to_bits().cmp(&rhs_bits).then(conv.dir)) } #[inline] @@ -76,19 +76,20 @@ macro_rules! fixed_cmp_fixed { (true, false) => return true, _ => {} } - let (rhs_128, dir, overflow) = rhs.to_bits().to_fixed_dir_overflow( + let conv = rhs.to_bits().to_fixed_helper( <$Rhs>::FRAC_NBITS as i32, Self::FRAC_NBITS, Self::INT_NBITS, ); - if overflow { + if conv.overflow { return !rhs.to_bits().is_negative(); } - let rhs_bits = match rhs_128 { + let rhs_bits = match conv.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) + self.to_bits() < rhs_bits + || (self.to_bits() == rhs_bits && conv.dir == Ordering::Less) } #[inline] @@ -189,13 +190,12 @@ macro_rules! fixed_cmp_float { if !SealedFloat::is_finite(*rhs) { return false; } - let (rhs_128, dir, overflow) = - rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); - let rhs_bits = match rhs_128 { + let conv = rhs.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS); + let rhs_bits = match conv.bits { Widest::Unsigned(bits) => bits as ::Bits, Widest::Negative(bits) => bits as ::Bits, }; - dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits() + conv.dir == Ordering::Equal && !conv.overflow && rhs_bits == self.to_bits() } } @@ -225,20 +225,19 @@ macro_rules! fixed_cmp_float { (true, false) => return Some(Ordering::Less), _ => {} } - let (rhs_128, dir, overflow) = - rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); - if overflow { + let conv = rhs.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS); + if conv.overflow { return if rhs_is_neg { Some(Ordering::Greater) } else { Some(Ordering::Less) }; } - let rhs_bits = match rhs_128 { + let rhs_bits = match conv.bits { Widest::Unsigned(bits) => bits as ::Bits, Widest::Negative(bits) => bits as ::Bits, }; - Some(self.to_bits().cmp(&rhs_bits).then(dir)) + Some(self.to_bits().cmp(&rhs_bits).then(conv.dir)) } #[inline] @@ -255,17 +254,16 @@ macro_rules! fixed_cmp_float { (true, false) => return true, _ => {} } - let (rhs_128, dir, overflow) = - rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); - if overflow { + let conv = rhs.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS); + if conv.overflow { return !rhs_is_neg; } - let rhs_bits = match rhs_128 { + let rhs_bits = match conv.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) + lhs_bits < rhs_bits || (lhs_bits == rhs_bits && conv.dir == Ordering::Less) } #[inline] @@ -304,17 +302,16 @@ macro_rules! fixed_cmp_float { (true, false) => return true, _ => {} } - let (lhs_128, dir, overflow) = - self.to_fixed_dir_overflow(<$Fix>::FRAC_NBITS, <$Fix>::INT_NBITS); - if overflow { + let conv = self.to_fixed_helper(<$Fix>::FRAC_NBITS, <$Fix>::INT_NBITS); + if conv.overflow { return lhs_is_neg; } - let lhs_bits = match lhs_128 { + let lhs_bits = match conv.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) + lhs_bits < rhs_bits || (lhs_bits == rhs_bits && conv.dir == Ordering::Greater) } #[inline] diff --git a/src/sealed.rs b/src/sealed.rs index ece0d76..3145c17 100644 --- a/src/sealed.rs +++ b/src/sealed.rs @@ -18,7 +18,7 @@ This module contains sealed traits. */ pub(crate) use crate::{ - sealed_fixed::{SealedFixed, Widest}, + sealed_fixed::{SealedFixed, ToFixedHelper, Widest}, sealed_float::SealedFloat, sealed_int::SealedInt, }; diff --git a/src/sealed_fixed.rs b/src/sealed_fixed.rs index a8a3850..86b7e89 100644 --- a/src/sealed_fixed.rs +++ b/src/sealed_fixed.rs @@ -21,6 +21,7 @@ use crate::{ FixedU8, }; use core::{ + cmp::Ordering, fmt::{Debug, Display}, hash::Hash, }; @@ -32,6 +33,12 @@ pub enum Widest { Negative(i128), } +pub struct ToFixedHelper { + pub(crate) bits: Widest, + pub(crate) dir: Ordering, + pub(crate) overflow: bool, +} + pub trait SealedFixed: Copy { type FracNBits: Unsigned; type SBits: SealedInt; @@ -102,12 +109,12 @@ macro_rules! sealed_fixed { #[inline] fn saturating_from_fixed(val: F) -> Self { - let (value, _, overflow) = val.to_sbits().to_fixed_dir_overflow( + let conv = val.to_sbits().to_fixed_helper( F::FRAC_NBITS as i32, Self::FRAC_NBITS, Self::INT_NBITS, ); - if overflow { + if conv.overflow { return if val.to_sbits().is_negative() { SealedFixed::from_sbits(Self::SBits::min_value()) } else { @@ -116,7 +123,7 @@ macro_rules! sealed_fixed { } let bits = if_signed_unsigned!( $Signedness, - match value { + match conv.bits { Widest::Unsigned(bits) => { if (bits as Self::SBits) < 0 { return $Fixed::from_bits(Self::SBits::max_value()); @@ -125,7 +132,7 @@ macro_rules! sealed_fixed { } Widest::Negative(bits) => bits as Self::SBits, }, - match value { + match conv.bits { Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(_) => { return $Fixed::from_bits(Self::SBits::min_value()); @@ -137,31 +144,32 @@ macro_rules! sealed_fixed { #[inline] fn overflowing_from_fixed(val: F) -> (Self, bool) { - let (value, _, mut overflow) = val.to_sbits().to_fixed_dir_overflow( + let conv = val.to_sbits().to_fixed_helper( F::FRAC_NBITS as i32, Self::FRAC_NBITS, Self::INT_NBITS, ); + let mut new_overflow = false; let bits = if_signed_unsigned!( $Signedness, - match value { + match conv.bits { Widest::Unsigned(bits) => { if (bits as Self::SBits) < 0 { - overflow = true; + new_overflow = true; } bits as Self::SBits } Widest::Negative(bits) => bits as Self::SBits, }, - match value { + match conv.bits { Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(bits) => { - overflow = true; + new_overflow = true; bits as Self::SBits } }, ); - ($Fixed::from_bits(bits), overflow) + ($Fixed::from_bits(bits), conv.overflow || new_overflow) } #[inline] @@ -177,14 +185,13 @@ macro_rules! sealed_fixed { if !val.is_finite() { return saturated; } - let (value, _, overflow) = - val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); - if overflow { + let conv = val.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS); + if conv.overflow { return saturated; } let bits = if_signed_unsigned!( $Signedness, - match value { + match conv.bits { Widest::Unsigned(bits) => { if (bits as Self::SBits) < 0 { return Self::max_value(); @@ -193,7 +200,7 @@ macro_rules! sealed_fixed { } Widest::Negative(bits) => bits as Self::SBits, }, - match value { + match conv.bits { Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(_) => return Self::min_value(), }, @@ -205,28 +212,28 @@ macro_rules! sealed_fixed { if !val.is_finite() { panic!("{} is not finite", val.traits()); } - let (value, _, mut overflow) = - val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); + let conv = val.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS); + let mut new_overflow = false; let bits = if_signed_unsigned!( $Signedness, - match value { + match conv.bits { Widest::Unsigned(bits) => { if (bits as Self::SBits) < 0 { - overflow = true; + new_overflow = true; } bits as Self::SBits } Widest::Negative(bits) => bits as Self::SBits, }, - match value { + match conv.bits { Widest::Unsigned(bits) => bits as Self::SBits, Widest::Negative(bits) => { - overflow = true; + new_overflow = true; bits as Self::SBits } }, ); - ($Fixed::from_bits(bits), overflow) + ($Fixed::from_bits(bits), conv.overflow || new_overflow) } #[inline] diff --git a/src/sealed_float.rs b/src/sealed_float.rs index 3cc0842..0d66e2b 100644 --- a/src/sealed_float.rs +++ b/src/sealed_float.rs @@ -13,7 +13,7 @@ // and // . -use crate::sealed::{Fixed, SealedFixed, SealedInt, Widest}; +use crate::sealed::{Fixed, SealedFixed, SealedInt, ToFixedHelper, Widest}; use core::{ cmp::Ordering, fmt::{Debug, Display}, @@ -79,7 +79,7 @@ pub trait SealedFloat: Copy { fn from_neg_abs(neg: bool, abs: u128, frac_bits: u32, int_bits: u32) -> Self; // self must be finite, otherwise meaningless results are returned - fn to_fixed_dir_overflow(self, frac_bits: u32, int_bits: u32) -> (Widest, Ordering, bool); + fn to_fixed_helper(self, frac_bits: u32, int_bits: u32) -> ToFixedHelper; } macro_rules! sealed_float { @@ -212,11 +212,7 @@ macro_rules! sealed_float { } #[inline] - fn to_fixed_dir_overflow( - self, - dst_frac_bits: u32, - dst_int_bits: u32, - ) -> (Widest, Ordering, bool) { + fn to_fixed_helper(self, dst_frac_bits: u32, dst_int_bits: u32) -> ToFixedHelper { let prec = Self::PREC as i32; let (neg, exp, mut mantissa) = self.parts(); @@ -226,7 +222,11 @@ macro_rules! sealed_float { mantissa |= 1 << (prec - 1); } if mantissa == 0 { - return (Widest::Unsigned(0), Ordering::Equal, false); + return ToFixedHelper { + bits: Widest::Unsigned(0), + dir: Ordering::Equal, + overflow: false, + }; } let mut src_frac_bits = prec - 1 - exp; @@ -237,7 +237,11 @@ macro_rules! sealed_float { } else { Ordering::Less }; - return (Widest::Unsigned(0), dir, false); + return ToFixedHelper { + bits: Widest::Unsigned(0), + dir, + overflow: false, + }; } let mut dir = Ordering::Equal; if need_to_shr > 0 { @@ -262,9 +266,8 @@ macro_rules! sealed_float { mantissa = -mantissa; dir = dir.reverse(); } - let (fixed, _, overflow) = - mantissa.to_fixed_dir_overflow(src_frac_bits, dst_frac_bits, dst_int_bits); - (fixed, dir, overflow) + let conv = mantissa.to_fixed_helper(src_frac_bits, dst_frac_bits, dst_int_bits); + ToFixedHelper { dir, ..conv } } } }; diff --git a/src/sealed_int.rs b/src/sealed_int.rs index fd5ab47..e75392c 100644 --- a/src/sealed_int.rs +++ b/src/sealed_int.rs @@ -15,7 +15,7 @@ use crate::{ frac::{Bit, False, True, Unsigned, U0, U128, U16, U32, U64, U8}, - sealed::{Fixed, SealedFixed, Widest}, + sealed::{Fixed, SealedFixed, ToFixedHelper, Widest}, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64, FixedU8, }; @@ -94,12 +94,12 @@ pub trait SealedInt: Copy { fn overflowing_add(self, val: Self) -> (Self, bool); fn leading_zeros(self) -> u32; - fn to_fixed_dir_overflow( + fn to_fixed_helper( self, src_frac_bits: i32, dst_frac_bits: u32, dst_int_bits: u32, - ) -> (Widest, Ordering, bool); + ) -> ToFixedHelper; fn to_repr_fixed(self) -> Self::ReprFixed; @@ -219,17 +219,21 @@ macro_rules! sealed_int { } #[inline] - fn to_fixed_dir_overflow( + fn to_fixed_helper( self, src_frac_bits: i32, dst_frac_bits: u32, dst_int_bits: u32, - ) -> (Widest, Ordering, bool) { + ) -> ToFixedHelper { let src_bits = Self::NBITS as i32; let dst_bits = (dst_frac_bits + dst_int_bits) as i32; if self == 0 { - return (Widest::Unsigned(0), Ordering::Equal, false); + return ToFixedHelper { + bits:Widest::Unsigned(0), + dir:Ordering::Equal, + overflow:false, + }; } let leading_zeros = self.leading_zeros(); @@ -248,7 +252,11 @@ macro_rules! sealed_int { _ => unreachable!(), }; let dir = if lost_bits { Ordering::Less } else { Ordering::Equal }; - (Widest::Unsigned(bits), dir, overflow) + ToFixedHelper { + bits: Widest::Unsigned(bits), + dir, + overflow, + } } } }; @@ -281,17 +289,21 @@ macro_rules! sealed_int { } #[inline] - fn to_fixed_dir_overflow( + fn to_fixed_helper( self, src_frac_bits: i32, dst_frac_bits: u32, dst_int_bits: u32, - ) -> (Widest, Ordering, bool) { + ) -> ToFixedHelper { let src_bits = Self::NBITS as i32; let dst_bits = (dst_frac_bits + dst_int_bits) as i32; if self == 0 { - return (Widest::Unsigned(0), Ordering::Equal, false); + return ToFixedHelper { + bits: Widest::Unsigned(0), + dir: Ordering::Equal, + overflow: false, + }; } let need_to_shr = src_frac_bits - dst_frac_bits as i32; @@ -314,11 +326,12 @@ macro_rules! sealed_int { _ => unreachable!(), }; let dir = if lost_bits { Ordering::Less } else { Ordering::Equal }; - if self >= 0 { - (Widest::Unsigned(bits as u128), dir, overflow) + let bits = if self >= 0 { + Widest::Unsigned(bits as u128) } else { - (Widest::Negative(bits), dir, overflow) - } + Widest::Negative(bits) + }; + ToFixedHelper { bits, dir, overflow } } } };