simplify checked conversions for floats

This commit is contained in:
Trevor Spiteri 2019-08-03 02:06:18 +02:00
parent 91a4ba3de7
commit dad1cb298c
4 changed files with 89 additions and 109 deletions

View File

@ -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,

View File

@ -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)
}
);
};

View File

@ -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]

View File

@ -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;