simplify checked conversions for floats
This commit is contained in:
parent
91a4ba3de7
commit
dad1cb298c
|
@ -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,
|
||||
|
|
|
@ -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::<f32>(), 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 <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)
|
||||
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 <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)
|
||||
SealedFloat::overflowing_to_fixed(val)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<F>(float: F) -> Self
|
||||
where
|
||||
F: SealedFloat;
|
||||
fn overflowing_from_float<F>(float: F) -> (Self, bool)
|
||||
where
|
||||
F: Float;
|
||||
F: SealedFloat;
|
||||
fn to_float<F>(self) -> F
|
||||
where
|
||||
F: Float;
|
||||
F: SealedFloat;
|
||||
|
||||
#[inline]
|
||||
fn one() -> Option<Self> {
|
||||
|
@ -207,19 +210,83 @@ macro_rules! sealed_fixed {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn overflowing_from_float<F>(float: F) -> (Self, bool)
|
||||
fn saturating_from_float<F>(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 <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)
|
||||
}
|
||||
#[inline]
|
||||
fn overflowing_from_float<F>(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 <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)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_float<F>(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]
|
||||
|
|
|
@ -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(<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,
|
||||
}
|
||||
SealedFixed::saturating_from_float(self)
|
||||
}
|
||||
#[inline]
|
||||
fn wrapping_to_fixed<F>(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<F>(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<F>(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;
|
||||
|
|
Loading…
Reference in New Issue