use core::fmt::{Debug, Display};
use core::hash::Hash;
use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8};
use sealed::{Fixed, Float, SealedInt};
use {
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8,
};
pub enum Widest {
Unsigned(u128),
Negative(i128),
}
pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
type FracNBits: Unsigned;
type Bits: SealedInt;
const FRAC_NBITS: u32 = Self::FracNBits::U32;
const INT_NBITS: u32 = Self::Bits::NBITS - Self::FRAC_NBITS;
const FRAC_MASK: u128 = !Self::INT_MASK;
const INT_MASK: u128 =
!0 << (Self::FRAC_NBITS / 2) << (Self::FRAC_NBITS - Self::FRAC_NBITS / 2);
const FRAC_MSB: u128 = Self::FRAC_MASK ^ (Self::FRAC_MASK >> 1);
const INT_LSB: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1);
fn overflowing_from_fixed<F>(fixed: F) -> (Self, bool)
where
F: Fixed;
fn overflowing_from_float<F>(float: F) -> (Self, bool)
where
F: Float;
fn to_float<F>(self) -> F
where
F: Float;
#[inline]
fn one() -> Option<Self> {
let min_int_bits = if Self::Bits::IS_SIGNED { 2 } else { 1 };
if Self::INT_NBITS < min_int_bits {
None
} else {
Some(Self::from_bits(Self::Bits::one_shl(Self::FRAC_NBITS)))
}
}
#[inline]
fn minus_one() -> Option<Self> {
if !Self::Bits::IS_SIGNED || Self::INT_NBITS < 1 {
None
} else {
Some(Self::from_bits(Self::Bits::all_ones_shl(Self::FRAC_NBITS)))
}
}
fn from_bits(bits: Self::Bits) -> Self;
fn to_bits(self) -> Self::Bits;
fn parts(
self,
) -> (
bool,
<Self::Bits as SealedInt>::Unsigned,
<Self::Bits as SealedInt>::Unsigned,
);
fn wrapping_ceil(self) -> Self;
fn wrapping_floor(self) -> Self;
fn wrapping_round(self) -> Self;
fn wrapping_neg(self) -> Self;
fn wrapping_abs(self) -> Self;
}
macro_rules! sealed_fixed {
($Fixed:ident($Bits:ty, $Len:ty, $Signedness:tt)) => {
impl<Frac> SealedFixed for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
type FracNBits = Frac;
type Bits = $Bits;
#[inline]
fn overflowing_from_fixed<F>(fixed: F) -> (Self, bool)
where
F: Fixed,
{
$Fixed::overflowing_from_fixed(fixed)
}
#[inline]
fn overflowing_from_float<F>(float: F) -> (Self, bool)
where
F: Float,
{
$Fixed::overflowing_from_float(float)
}
#[inline]
fn to_float<F>(self) -> F
where
F: Float,
{
$Fixed::to_float(self)
}
#[inline]
fn from_bits(bits: Self::Bits) -> Self {
$Fixed::from_bits(bits)
}
#[inline]
fn to_bits(self) -> Self::Bits {
$Fixed::to_bits(self)
}
#[inline]
fn parts(
self,
) -> (
bool,
<Self::Bits as SealedInt>::Unsigned,
<Self::Bits as SealedInt>::Unsigned,
) {
let (neg, abs) = SealedInt::neg_abs(self.to_bits());
let (int_abs, frac_abs) = if Self::INT_NBITS == 0 {
(0, abs)
} else if Self::FRAC_NBITS == 0 {
(abs, 0)
} else {
((abs >> Self::FRAC_NBITS), (abs << Self::INT_NBITS))
};
(neg, int_abs, frac_abs)
}
#[inline]
fn wrapping_ceil(self) -> Self {
self.wrapping_ceil()
}
#[inline]
fn wrapping_floor(self) -> Self {
self.wrapping_floor()
}
#[inline]
fn wrapping_round(self) -> Self {
self.wrapping_round()
}
#[inline]
fn wrapping_neg(self) -> Self {
self.wrapping_neg()
}
#[inline]
fn wrapping_abs(self) -> Self {
if_signed_unsigned! {
$Signedness,
self.wrapping_abs(),
self,
}
}
}
};
}
sealed_fixed! { FixedI8(i8, U8, Signed) }
sealed_fixed! { FixedI16(i16, U16, Signed) }
sealed_fixed! { FixedI32(i32, U32, Signed) }
sealed_fixed! { FixedI64(i64, U64, Signed) }
sealed_fixed! { FixedI128(i128, U128, Signed) }
sealed_fixed! { FixedU8(u8, U8, Unsigned) }
sealed_fixed! { FixedU16(u16, U16, Unsigned) }
sealed_fixed! { FixedU32(u32, U32, Unsigned) }
sealed_fixed! { FixedU64(u64, U64, Unsigned) }
sealed_fixed! { FixedU128(u128, U128, Unsigned) }