diff --git a/src/lib.rs b/src/lib.rs index c27e217..7a1e266 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,7 +215,7 @@ use { crate::{ arith::MulDivDir, frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8}, - sealed::{Fixed, Float, Int, SealedFixed, SealedFloat, SealedInt, Widest}, + sealed::{Fixed, Float, Int, SealedFixed, SealedFloat, SealedInt}, }, core::{ cmp::Ordering, diff --git a/src/macros_from_to.rs b/src/macros_from_to.rs index 44711c1..e6a24df 100644 --- a/src/macros_from_to.rs +++ b/src/macros_from_to.rs @@ -289,10 +289,7 @@ assert_eq!(Fix::from_float(", where F: Float, { - let (wrapped, overflow) = Self::overflowing_from_float(val); - debug_assert!(!overflow, "{} overflows", val); - let _ = overflow; - wrapped + SealedFloat::to_fixed(val) } ); @@ -332,13 +329,7 @@ assert_eq!(max_fixed.to_float::(), std::f32::INFINITY); where F: Float, { - let (neg, abs) = self.to_bits().neg_abs(); - SealedFloat::from_neg_abs( - neg, - u128::from(abs), - Self::FRAC_NBITS, - Self::INT_NBITS, - ) + SealedFixed::to_float(self) } ); @@ -562,11 +553,7 @@ assert!(Fix::checked_from_float(std::f64::NAN).is_none()); where F: Float, { - if !val.is_finite() { - return None; - } - let (wrapped, overflow) = Self::overflowing_from_float(val); - if overflow { None } else { Some(wrapped) } + SealedFloat::checked_to_fixed(val) } ); @@ -799,39 +786,7 @@ assert_eq!(Fix::saturating_from_float(f64::NEG_INFINITY), Fix::min_value()); where F: Float, { - assert!(!val.is_nan(), "NaN"); - let saturated = if val.is_sign_negative() { - Self::min_value() - } else { - Self::max_value() - }; - if !val.is_finite() { - return saturated; - } - let (value, _, overflow) = val.to_fixed_dir_overflow( - Self::FRAC_NBITS, - Self::INT_NBITS, - ); - if overflow { - return saturated; - } - let bits = if_signed_unsigned!( - $Signedness, - match value { - Widest::Unsigned(bits) => { - if (bits as ::Bits) < 0 { - return Self::max_value(); - } - bits as ::Bits - } - Widest::Negative(bits) => bits as ::Bits, - }, - match value { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(_) => return Self::min_value(), - }, - ); - SealedFixed::from_bits(bits) + SealedFloat::saturating_to_fixed(val) } ); @@ -1076,7 +1031,7 @@ assert_eq!(Fix::wrapping_from_float(large), wrapped); where F: Float, { - Self::overflowing_from_float(val).0 + SealedFloat::wrapping_to_fixed(val) } ); @@ -1338,33 +1293,7 @@ assert_eq!(Fix::overflowing_from_float(large), (wrapped, true)); where F: Float, { - if !val.is_finite() { - panic!("{} is not finite", val); - } - let (value, _, mut overflow) = val.to_fixed_dir_overflow( - Self::FRAC_NBITS, - Self::INT_NBITS, - ); - let bits = if_signed_unsigned!( - $Signedness, - match value { - Widest::Unsigned(bits) => { - if (bits as ::Bits) < 0 { - overflow = true; - } - bits as ::Bits - } - Widest::Negative(bits) => bits as ::Bits, - }, - match value { - Widest::Unsigned(bits) => bits as ::Bits, - Widest::Negative(bits) => { - overflow = true; - bits as ::Bits - } - }, - ); - (SealedFixed::from_bits(bits), overflow) + SealedFloat::overflowing_to_fixed(val) } ); }; diff --git a/src/sealed_fixed.rs b/src/sealed_fixed.rs index 6ac280d..fa9bb66 100644 --- a/src/sealed_fixed.rs +++ b/src/sealed_fixed.rs @@ -16,7 +16,7 @@ use { crate::{ frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8}, - sealed::{Fixed, Float, SealedInt}, + sealed::{Fixed, SealedFloat, SealedInt}, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64, FixedU8, }, @@ -84,12 +84,15 @@ pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord { where F: Fixed; + fn saturating_from_float(float: F) -> Self + where + F: SealedFloat; fn overflowing_from_float(float: F) -> (Self, bool) where - F: Float; + F: SealedFloat; fn to_float(self) -> F where - F: Float; + F: SealedFloat; #[inline] fn one() -> Option { @@ -207,19 +210,83 @@ macro_rules! sealed_fixed { } #[inline] - fn overflowing_from_float(float: F) -> (Self, bool) + fn saturating_from_float(val: F) -> Self where - F: Float, + F: SealedFloat, { - $Fixed::overflowing_from_float(float) + if val.is_nan() { + panic!("NaN"); + } + let saturated = if val.is_sign_negative() { + Self::min_value() + } else { + Self::max_value() + }; + if !val.is_finite() { + return saturated; + } + let (value, _, overflow) = + val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); + if overflow { + return saturated; + } + let bits = if_signed_unsigned!( + $Signedness, + match value { + Widest::Unsigned(bits) => { + if (bits as ::Bits) < 0 { + return Self::max_value(); + } + bits as ::Bits + } + Widest::Negative(bits) => bits as ::Bits, + }, + match value { + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(_) => return Self::min_value(), + }, + ); + SealedFixed::from_bits(bits) + } + #[inline] + fn overflowing_from_float(val: F) -> (Self, bool) + where + F: SealedFloat, + { + if !val.is_finite() { + panic!("{} is not finite", val); + } + let (value, _, mut overflow) = + val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS); + let bits = if_signed_unsigned!( + $Signedness, + match value { + Widest::Unsigned(bits) => { + if (bits as ::Bits) < 0 { + overflow = true; + } + bits as ::Bits + } + Widest::Negative(bits) => bits as ::Bits, + }, + match value { + Widest::Unsigned(bits) => bits as ::Bits, + Widest::Negative(bits) => { + overflow = true; + bits as ::Bits + } + }, + ); + (SealedFixed::from_bits(bits), overflow) } #[inline] fn to_float(self) -> F where - F: Float, + F: SealedFloat, { - $Fixed::to_float(self) + let (neg, abs) = self.to_bits().neg_abs(); + SealedFloat::from_neg_abs(neg, u128::from(abs), Self::FRAC_NBITS, Self::INT_NBITS) } #[inline] diff --git a/src/sealed_float.rs b/src/sealed_float.rs index 4f93f92..c810790 100644 --- a/src/sealed_float.rs +++ b/src/sealed_float.rs @@ -64,8 +64,8 @@ pub trait SealedFloat: Copy + Debug + Display { return None; } match Self::overflowing_to_fixed(self) { - (wrapped, false) => Some(wrapped), (_, true) => None, + (wrapped, false) => Some(wrapped), } } #[inline] @@ -73,19 +73,7 @@ pub trait SealedFloat: Copy + Debug + Display { where F: Fixed, { - assert!(!self.is_nan(), "NaN"); - let saturated = if self.is_sign_negative() { - F::from_bits(::Bits::min_value()) - } else { - F::from_bits(::Bits::max_value()) - }; - if !self.is_finite() { - return saturated; - } - match Self::overflowing_to_fixed(self) { - (wrapped, false) => wrapped, - (_, true) => saturated, - } + SealedFixed::saturating_from_float(self) } #[inline] fn wrapping_to_fixed(self) -> F @@ -95,9 +83,13 @@ pub trait SealedFloat: Copy + Debug + Display { let (wrapped, _) = Self::overflowing_to_fixed(self); wrapped } + #[inline] fn overflowing_to_fixed(self) -> (F, bool) where - F: Fixed; + F: Fixed, + { + SealedFixed::overflowing_from_float(self) + } fn from_neg_abs(neg: bool, abs: u128, frac_bits: u32, int_bits: u32) -> Self; // self must be finite, otherwise meaningless results are returned @@ -171,14 +163,6 @@ macro_rules! sealed_float { Self::from_bits(bits) } - #[inline] - fn overflowing_to_fixed(self) -> (F, bool) - where - F: Fixed, - { - F::overflowing_from_float(self) - } - #[inline] fn from_neg_abs(neg: bool, abs: u128, frac_bits: u32, int_bits: u32) -> $Float { let fix_bits = frac_bits + int_bits;