simplify checked conversions for int and fixed
The actual implementations are now in SealedInt and SealedFixed. Both macros_from_to.rs and sealed.rs directly defer to those implementations.
This commit is contained in:
parent
62457d201d
commit
99668c5a5e
|
@ -90,10 +90,7 @@ assert_eq!(Dst::from_fixed(src >> 4), Dst::from_bits(1));
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedFixed::from_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -131,10 +128,7 @@ assert_eq!((src >> 4u32).to_fixed::<Dst>(), Dst::from_bits(1));
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <F as SealedFixed>::overflowing_from_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedFixed::from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -187,10 +181,7 @@ assert_eq!(Fix::from_int(",
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_from_int(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedInt::to_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -246,10 +237,7 @@ assert_eq!(",
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
let (wrapped, overflow) = <I as SealedInt>::overflowing_from_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedInt::from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -383,8 +371,7 @@ assert!(Dst::checked_from_fixed(too_large).is_none());
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_from_fixed(val);
|
||||
if overflow { None } else { Some(wrapped) }
|
||||
SealedFixed::checked_from_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -418,10 +405,7 @@ assert!(Src::max_value().checked_to_fixed::<TooFewIntBits>().is_none());
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <F as SealedFixed>::overflowing_from_fixed(self) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
SealedFixed::checked_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -473,8 +457,7 @@ assert!(Fix::checked_from_int(too_small).is_none());
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_from_int(val);
|
||||
if overflow { None } else { Some(wrapped) }
|
||||
SealedInt::checked_to_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -535,10 +518,7 @@ assert!(AllInt::",
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
match <I as SealedInt>::overflowing_from_fixed(self) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
SealedInt::checked_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -625,35 +605,7 @@ assert_eq!(Dst::saturating_from_fixed(too_small), Dst::min_value());
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (value, _, overflow) = val.to_bits().to_fixed_dir_overflow(
|
||||
F::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
if overflow {
|
||||
return if val.to_bits().is_negative() {
|
||||
Self::min_value()
|
||||
} else {
|
||||
Self::max_value()
|
||||
};
|
||||
}
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as <Self as SealedFixed>::Bits) < 0 {
|
||||
return Self::max_value();
|
||||
}
|
||||
bits as <Self as SealedFixed>::Bits
|
||||
}
|
||||
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
},
|
||||
match value {
|
||||
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
Widest::Negative(_) => return Self::min_value(),
|
||||
},
|
||||
);
|
||||
SealedFixed::from_bits(bits)
|
||||
SealedFixed::saturating_from_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -685,16 +637,7 @@ assert_eq!(saturated, TooFewIntBits::max_value());
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <F as SealedFixed>::overflowing_from_fixed(self) {
|
||||
(wrapped, false) => wrapped,
|
||||
(_, true) => {
|
||||
if self.to_bits().is_negative() {
|
||||
F::from_bits(F::Bits::min_value())
|
||||
} else {
|
||||
F::from_bits(F::Bits::max_value())
|
||||
}
|
||||
}
|
||||
}
|
||||
SealedFixed::saturating_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -745,35 +688,7 @@ assert_eq!(Fix::saturating_from_int(too_small), Fix::min_value());
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
let (value, _, overflow) = val.to_fixed_dir_overflow(
|
||||
0,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
if overflow {
|
||||
return if val.is_negative() {
|
||||
Self::min_value()
|
||||
} else {
|
||||
Self::max_value()
|
||||
};
|
||||
}
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as <Self as SealedFixed>::Bits) < 0 {
|
||||
return Self::max_value();
|
||||
}
|
||||
bits as <Self as SealedFixed>::Bits
|
||||
}
|
||||
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
},
|
||||
match value {
|
||||
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
Widest::Negative(_) => return Self::min_value(),
|
||||
},
|
||||
);
|
||||
SealedFixed::from_bits(bits)
|
||||
SealedInt::saturating_to_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -842,16 +757,7 @@ assert_eq!(",
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
match <I as SealedInt>::overflowing_from_fixed(self) {
|
||||
(wrapped, false) => wrapped,
|
||||
(_, true) => {
|
||||
if self.to_bits().is_negative() {
|
||||
I::min_value()
|
||||
} else {
|
||||
I::max_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
SealedInt::saturating_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -965,7 +871,7 @@ assert_eq!(Dst::wrapping_from_fixed(too_large), wrapped);
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
Self::overflowing_from_fixed(val).0
|
||||
SealedFixed::wrapping_from_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -998,7 +904,7 @@ assert_eq!(Src::max_value().wrapping_to_fixed::<TooFewIntBits>(), wrapped);
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<F as SealedFixed>::overflowing_from_fixed(self).0
|
||||
SealedFixed::wrapping_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1049,7 +955,7 @@ assert_eq!(Fix::wrapping_from_int(large), wrapped);
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
Self::overflowing_from_int(val).0
|
||||
SealedInt::wrapping_to_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1118,7 +1024,7 @@ assert_eq!(",
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
<I as SealedInt>::overflowing_from_fixed(self).0
|
||||
SealedInt::wrapping_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1216,31 +1122,7 @@ assert_eq!(Dst::overflowing_from_fixed(too_large), (wrapped, true));
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (value, _, mut overflow) = val.to_bits().to_fixed_dir_overflow(
|
||||
F::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as <Self as SealedFixed>::Bits) < 0 {
|
||||
overflow = true;
|
||||
}
|
||||
bits as <Self as SealedFixed>::Bits
|
||||
}
|
||||
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
},
|
||||
match value {
|
||||
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
Widest::Negative(bits) => {
|
||||
overflow = true;
|
||||
bits as <Self as SealedFixed>::Bits
|
||||
}
|
||||
},
|
||||
);
|
||||
(SealedFixed::from_bits(bits), overflow)
|
||||
SealedFixed::overflowing_from_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1277,7 +1159,7 @@ assert_eq!(Src::max_value().overflowing_to_fixed::<TooFewIntBits>(), (wrapped, t
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<F as SealedFixed>::overflowing_from_fixed(self)
|
||||
SealedFixed::overflowing_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1332,31 +1214,7 @@ assert_eq!(Fix::overflowing_from_int(large), (wrapped, true));
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
let (value, _, mut overflow) = val.to_fixed_dir_overflow(
|
||||
0,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as <Self as SealedFixed>::Bits) < 0 {
|
||||
overflow = true;
|
||||
}
|
||||
bits as <Self as SealedFixed>::Bits
|
||||
}
|
||||
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
},
|
||||
match value {
|
||||
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
|
||||
Widest::Negative(bits) => {
|
||||
overflow = true;
|
||||
bits as <Self as SealedFixed>::Bits
|
||||
}
|
||||
},
|
||||
);
|
||||
(SealedFixed::from_bits(bits), overflow)
|
||||
SealedInt::overflowing_to_fixed(val)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1424,7 +1282,7 @@ assert_eq!(does_not_fit.overflowing_to_int::<",
|
|||
where
|
||||
I: Int,
|
||||
{
|
||||
<I as SealedInt>::overflowing_from_fixed(self)
|
||||
SealedInt::overflowing_from_fixed(self)
|
||||
}
|
||||
);
|
||||
|
||||
|
|
120
src/sealed.rs
120
src/sealed.rs
|
@ -159,51 +159,35 @@ macro_rules! checked_int {
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <Self as SealedInt>::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedInt::from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_from_fixed<F>(val: F) -> Option<Self>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <Self as SealedInt>::overflowing_from_fixed(val) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
SealedInt::checked_from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn saturating_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <Self as SealedInt>::overflowing_from_fixed(val) {
|
||||
(wrapped, false) => wrapped,
|
||||
(_, true) => {
|
||||
if val.to_bits().is_negative() {
|
||||
Self::min_value()
|
||||
} else {
|
||||
Self::max_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
SealedInt::saturating_from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = <Self as SealedInt>::overflowing_from_fixed(val);
|
||||
wrapped
|
||||
SealedInt::wrapping_from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_from_fixed<F>(val: F) -> (Self, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<Self as SealedInt>::overflowing_from_fixed(val)
|
||||
SealedInt::overflowing_from_fixed(val)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,51 +197,35 @@ macro_rules! checked_int {
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <Self as SealedInt>::overflowing_to_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedInt::to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_to_fixed<F>(self) -> Option<F>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <Self as SealedInt>::overflowing_to_fixed(self) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
SealedInt::checked_to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn saturating_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <Self as SealedInt>::overflowing_to_fixed(self) {
|
||||
(wrapped, false) => wrapped,
|
||||
(_, true) => {
|
||||
if self.is_negative() {
|
||||
F::from_bits(<F as SealedFixed>::Bits::min_value())
|
||||
} else {
|
||||
F::from_bits(<F as SealedFixed>::Bits::max_value())
|
||||
}
|
||||
}
|
||||
}
|
||||
SealedInt::saturating_to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = <Self as SealedInt>::overflowing_to_fixed(self);
|
||||
wrapped
|
||||
SealedInt::wrapping_to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_to_fixed<F>(self) -> (F, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<Self as SealedInt>::overflowing_to_fixed(self)
|
||||
SealedInt::overflowing_to_fixed(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -322,57 +290,35 @@ macro_rules! checked_float {
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <Self as SealedFloat>::overflowing_to_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedFloat::to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_to_fixed<F>(self) -> Option<F>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
if !self.is_finite() {
|
||||
return None;
|
||||
}
|
||||
match <Self as SealedFloat>::overflowing_to_fixed(self) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
SealedFloat::checked_to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn saturating_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
assert!(!self.is_nan(), "NaN");
|
||||
let saturated = if self.is_sign_negative() {
|
||||
F::from_bits(<F as SealedFixed>::Bits::min_value())
|
||||
} else {
|
||||
F::from_bits(<F as SealedFixed>::Bits::max_value())
|
||||
};
|
||||
if !self.is_finite() {
|
||||
return saturated;
|
||||
}
|
||||
match <Self as SealedFloat>::overflowing_to_fixed(self) {
|
||||
(wrapped, false) => wrapped,
|
||||
(_, true) => saturated,
|
||||
}
|
||||
SealedFloat::saturating_to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = <Self as SealedFloat>::overflowing_to_fixed(self);
|
||||
wrapped
|
||||
SealedFloat::wrapping_to_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_to_fixed<F>(self) -> (F, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<Self as SealedFloat>::overflowing_to_fixed(self)
|
||||
SealedFloat::overflowing_to_fixed(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -394,44 +340,35 @@ macro_rules! checked_fixed {
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <Self as SealedFixed>::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedFixed::from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_from_fixed<F>(val: F) -> Option<Self>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <Self as SealedFixed>::overflowing_from_fixed(val);
|
||||
if overflow {
|
||||
None
|
||||
} else {
|
||||
Some(wrapped)
|
||||
}
|
||||
SealedFixed::checked_from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn saturating_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<Self as SealedFixed>::saturating_from_fixed(val)
|
||||
SealedFixed::saturating_from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = <Self as SealedFixed>::overflowing_from_fixed(val);
|
||||
wrapped
|
||||
SealedFixed::wrapping_from_fixed(val)
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_from_fixed<F>(val: F) -> (Self, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<Self as SealedFixed>::overflowing_from_fixed(val)
|
||||
SealedFixed::overflowing_from_fixed(val)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,42 +381,35 @@ macro_rules! checked_fixed {
|
|||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = <F as SealedFixed>::overflowing_from_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
SealedFixed::from_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_to_fixed<F>(self) -> Option<F>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match <F as SealedFixed>::overflowing_from_fixed(self) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
SealedFixed::checked_from_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn saturating_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<F as SealedFixed>::saturating_from_fixed(self)
|
||||
SealedFixed::saturating_from_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = <F as SealedFixed>::overflowing_from_fixed(self);
|
||||
wrapped
|
||||
SealedFixed::wrapping_from_fixed(self)
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_to_fixed<F>(self) -> (F, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
<F as SealedFixed>::overflowing_from_fixed(self)
|
||||
SealedFixed::overflowing_from_fixed(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -49,9 +49,37 @@ pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
|
|||
// 0 for no int bits
|
||||
const INT_LSB: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1);
|
||||
|
||||
#[inline]
|
||||
fn from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = SealedFixed::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
#[inline]
|
||||
fn checked_from_fixed<F>(val: F) -> Option<Self>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match SealedFixed::overflowing_from_fixed(val) {
|
||||
(_, true) => None,
|
||||
(wrapped, false) => Some(wrapped),
|
||||
}
|
||||
}
|
||||
fn saturating_from_fixed<F>(fixed: F) -> Self
|
||||
where
|
||||
F: Fixed;
|
||||
#[inline]
|
||||
fn wrapping_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = SealedFixed::overflowing_from_fixed(val);
|
||||
wrapped
|
||||
}
|
||||
fn overflowing_from_fixed<F>(fixed: F) -> (Self, bool)
|
||||
where
|
||||
F: Fixed;
|
||||
|
@ -109,19 +137,73 @@ macro_rules! sealed_fixed {
|
|||
type Bits = $Bits;
|
||||
|
||||
#[inline]
|
||||
fn saturating_from_fixed<F>(fixed: F) -> Self
|
||||
fn saturating_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
$Fixed::saturating_from_fixed(fixed)
|
||||
let (value, _, overflow) = val.to_bits().to_fixed_dir_overflow(
|
||||
F::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
if overflow {
|
||||
return if val.to_bits().is_negative() {
|
||||
Self::from_bits(Self::Bits::min_value())
|
||||
} else {
|
||||
Self::from_bits(Self::Bits::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());
|
||||
}
|
||||
bits as Self::Bits
|
||||
}
|
||||
Widest::Negative(bits) => bits as Self::Bits,
|
||||
},
|
||||
match value {
|
||||
Widest::Unsigned(bits) => bits as Self::Bits,
|
||||
Widest::Negative(_) => {
|
||||
return Self::from_bits(Self::Bits::min_value());
|
||||
}
|
||||
},
|
||||
);
|
||||
SealedFixed::from_bits(bits)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn overflowing_from_fixed<F>(fixed: F) -> (Self, bool)
|
||||
fn overflowing_from_fixed<F>(val: F) -> (Self, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
$Fixed::overflowing_from_fixed(fixed)
|
||||
let (value, _, mut overflow) = val.to_bits().to_fixed_dir_overflow(
|
||||
F::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as Self::Bits) < 0 {
|
||||
overflow = true;
|
||||
}
|
||||
bits as Self::Bits
|
||||
}
|
||||
Widest::Negative(bits) => bits as Self::Bits,
|
||||
},
|
||||
match value {
|
||||
Widest::Unsigned(bits) => bits as Self::Bits,
|
||||
Widest::Negative(bits) => {
|
||||
overflow = true;
|
||||
bits as Self::Bits
|
||||
}
|
||||
},
|
||||
);
|
||||
(SealedFixed::from_bits(bits), overflow)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#[cfg(feature = "f16")]
|
||||
use half::f16;
|
||||
use {
|
||||
crate::sealed::{Fixed, SealedInt, Widest},
|
||||
crate::sealed::{Fixed, SealedFixed, SealedInt, Widest},
|
||||
core::{
|
||||
cmp::Ordering,
|
||||
fmt::{Debug, Display},
|
||||
|
@ -45,6 +45,56 @@ pub trait SealedFloat: Copy + Debug + Display {
|
|||
fn parts(self) -> (bool, i32, Self::Bits);
|
||||
fn from_parts(sign: bool, exp: i32, mant: Self::Bits) -> Self;
|
||||
|
||||
#[inline]
|
||||
fn to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
#[inline]
|
||||
fn checked_to_fixed<F>(self) -> Option<F>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
if !self.is_finite() {
|
||||
return None;
|
||||
}
|
||||
match Self::overflowing_to_fixed(self) {
|
||||
(wrapped, false) => Some(wrapped),
|
||||
(_, true) => None,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn saturating_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
assert!(!self.is_nan(), "NaN");
|
||||
let saturated = if self.is_sign_negative() {
|
||||
F::from_bits(<F as SealedFixed>::Bits::min_value())
|
||||
} else {
|
||||
F::from_bits(<F as SealedFixed>::Bits::max_value())
|
||||
};
|
||||
if !self.is_finite() {
|
||||
return saturated;
|
||||
}
|
||||
match Self::overflowing_to_fixed(self) {
|
||||
(wrapped, false) => wrapped,
|
||||
(_, true) => saturated,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = Self::overflowing_to_fixed(self);
|
||||
wrapped
|
||||
}
|
||||
fn overflowing_to_fixed<F>(self) -> (F, bool)
|
||||
where
|
||||
F: Fixed;
|
||||
|
|
|
@ -36,9 +36,72 @@ pub trait SealedInt: Copy + Ord + Debug + Display {
|
|||
const IS_SIGNED: bool = Self::IsSigned::BOOL;
|
||||
const MSB: Self;
|
||||
|
||||
fn overflowing_from_fixed<F>(fixed: F) -> (Self, bool)
|
||||
#[inline]
|
||||
fn from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
#[inline]
|
||||
fn checked_from_fixed<F>(val: F) -> Option<Self>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match Self::overflowing_from_fixed(val) {
|
||||
(_, true) => None,
|
||||
(wrapped, false) => Some(wrapped),
|
||||
}
|
||||
}
|
||||
fn saturating_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed;
|
||||
#[inline]
|
||||
fn wrapping_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = Self::overflowing_from_fixed(val);
|
||||
wrapped
|
||||
}
|
||||
fn overflowing_from_fixed<F>(val: F) -> (Self, bool)
|
||||
where
|
||||
F: Fixed;
|
||||
|
||||
#[inline]
|
||||
fn to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
#[inline]
|
||||
fn checked_to_fixed<F>(self) -> Option<F>
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
match Self::overflowing_to_fixed(self) {
|
||||
(_, true) => None,
|
||||
(wrapped, false) => Some(wrapped),
|
||||
}
|
||||
}
|
||||
fn saturating_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed;
|
||||
#[inline]
|
||||
fn wrapping_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, _) = Self::overflowing_to_fixed(self);
|
||||
wrapped
|
||||
}
|
||||
fn overflowing_to_fixed<F>(self) -> (F, bool)
|
||||
where
|
||||
F: Fixed;
|
||||
|
@ -85,21 +148,35 @@ macro_rules! sealed_int {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn overflowing_from_fixed<F>(fixed: F) -> (Self, bool)
|
||||
fn saturating_from_fixed<F>(val: F) -> Self
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::ReprFixed::overflowing_from_fixed(fixed);
|
||||
let saturated = Self::ReprFixed::saturating_from_fixed(val);
|
||||
IntRepr::from_int_repr(saturated.to_bits())
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_from_fixed<F>(val: F) -> (Self, bool)
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
let (wrapped, overflow) = Self::ReprFixed::overflowing_from_fixed(val);
|
||||
(IntRepr::from_int_repr(wrapped.to_bits()), overflow)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn saturating_to_fixed<F>(self) -> F
|
||||
where
|
||||
F: Fixed,
|
||||
{
|
||||
SealedFixed::saturating_from_fixed(self.to_repr_fixed())
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_to_fixed<F>(self) -> (F, bool)
|
||||
where
|
||||
F: Fixed
|
||||
{
|
||||
let from_bits = Self::ReprFixed::from_bits(self.int_repr());
|
||||
<F as SealedFixed>::overflowing_from_fixed(from_bits)
|
||||
SealedFixed::overflowing_from_fixed(self.to_repr_fixed())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Reference in New Issue