use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8};
#[cfg(feature = "f16")]
use half::f16;
pub(crate) use sealed_fixed::{SealedFixed, Widest};
pub(crate) use sealed_float::SealedFloat;
pub(crate) use sealed_int::SealedInt;
use {
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8,
};
pub trait Int: SealedInt {
#[inline]
fn from_fixed<F>(val: F) -> Self
where
F: Fixed,
{
let (wrapped, overflow) = <Self as SealedInt>::overflowing_from_fixed(val);
debug_assert!(!overflow, "{} overflows", val);
let _ = overflow;
wrapped
}
#[inline]
fn to_fixed<F>(self) -> F
where
F: Fixed,
{
let (wrapped, overflow) = <Self as SealedInt>::overflowing_to_fixed(self);
debug_assert!(!overflow, "{} overflows", self);
let _ = overflow;
wrapped
}
#[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,
}
}
#[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,
}
}
#[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()
}
}
}
}
#[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())
}
}
}
}
#[inline]
fn wrapping_from_fixed<F>(val: F) -> Self
where
F: Fixed,
{
<Self as SealedInt>::overflowing_from_fixed(val).0
}
#[inline]
fn wrapping_to_fixed<F>(self) -> F
where
F: Fixed,
{
<Self as SealedInt>::overflowing_to_fixed(self).0
}
#[inline]
fn overflowing_from_fixed<F>(val: F) -> (Self, bool)
where
F: Fixed,
{
<Self as SealedInt>::overflowing_from_fixed(val)
}
#[inline]
fn overflowing_to_fixed<F>(self) -> (F, bool)
where
F: Fixed,
{
<Self as SealedInt>::overflowing_to_fixed(self)
}
}
pub trait Float: SealedFloat {
#[inline]
fn from_fixed<F>(val: F) -> Self
where
F: Fixed,
{
val.to_float()
}
#[inline]
fn to_fixed<F>(self) -> F
where
F: Fixed,
{
let (wrapped, overflow) = <Self as SealedFloat>::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 as SealedFloat>::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 as SealedFloat>::overflowing_to_fixed(self) {
(wrapped, false) => wrapped,
(_, true) => saturated,
}
}
#[inline]
fn wrapping_to_fixed<F>(self) -> F
where
F: Fixed,
{
<Self as SealedFloat>::overflowing_to_fixed(self).0
}
#[inline]
fn overflowing_to_fixed<F>(self) -> (F, bool)
where
F: Fixed,
{
<Self as SealedFloat>::overflowing_to_fixed(self)
}
}
pub trait Fixed: SealedFixed {}
impl Int for i8 {}
impl Int for i16 {}
impl Int for i32 {}
impl Int for i64 {}
impl Int for i128 {}
impl Int for isize {}
impl Int for u8 {}
impl Int for u16 {}
impl Int for u32 {}
impl Int for u64 {}
impl Int for u128 {}
impl Int for usize {}
#[cfg(feature = "f16")]
impl Float for f16 {}
impl Float for f32 {}
impl Float for f64 {}
impl<Frac> Fixed for FixedI8<Frac> where Frac: Unsigned + IsLessOrEqual<U8, Output = True> {}
impl<Frac> Fixed for FixedI16<Frac> where Frac: Unsigned + IsLessOrEqual<U16, Output = True> {}
impl<Frac> Fixed for FixedI32<Frac> where Frac: Unsigned + IsLessOrEqual<U32, Output = True> {}
impl<Frac> Fixed for FixedI64<Frac> where Frac: Unsigned + IsLessOrEqual<U64, Output = True> {}
impl<Frac> Fixed for FixedI128<Frac> where Frac: Unsigned + IsLessOrEqual<U128, Output = True> {}
impl<Frac> Fixed for FixedU8<Frac> where Frac: Unsigned + IsLessOrEqual<U8, Output = True> {}
impl<Frac> Fixed for FixedU16<Frac> where Frac: Unsigned + IsLessOrEqual<U16, Output = True> {}
impl<Frac> Fixed for FixedU32<Frac> where Frac: Unsigned + IsLessOrEqual<U32, Output = True> {}
impl<Frac> Fixed for FixedU64<Frac> where Frac: Unsigned + IsLessOrEqual<U64, Output = True> {}
impl<Frac> Fixed for FixedU128<Frac> where Frac: Unsigned + IsLessOrEqual<U128, Output = True> {}