add Bits, from_bits, to_bits to Fixed trait; and add it to prelude

This commit is contained in:
Trevor Spiteri 2019-08-03 17:09:53 +02:00
parent e9b256979b
commit 320147370f
6 changed files with 135 additions and 128 deletions

View File

@ -18,7 +18,7 @@ use half::f16;
use {
crate::{
frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8},
sealed::{SealedFixed, SealedFloat, SealedInt, Widest},
sealed::{Fixed, SealedFixed, SealedFloat, SealedInt, Widest},
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8,
},
@ -40,8 +40,8 @@ macro_rules! fixed_cmp_fixed {
Self::INT_NBITS,
);
let rhs_bits = match rhs_128 {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
};
dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits()
}
@ -72,8 +72,8 @@ macro_rules! fixed_cmp_fixed {
};
}
let rhs_bits = match rhs_128 {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
};
Some(self.to_bits().cmp(&rhs_bits).then(dir))
}
@ -94,8 +94,8 @@ macro_rules! fixed_cmp_fixed {
return !rhs.to_bits().is_negative();
}
let rhs_bits = match rhs_128 {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
};
self.to_bits() < rhs_bits || (self.to_bits() == rhs_bits && dir == Ordering::Less)
}
@ -216,8 +216,8 @@ macro_rules! fixed_cmp_float {
let (rhs_128, dir, overflow) =
rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
let rhs_bits = match rhs_128 {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
};
dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits()
}
@ -265,8 +265,8 @@ macro_rules! fixed_cmp_float {
};
}
let rhs_bits = match rhs_128 {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
};
Some(self.to_bits().cmp(&rhs_bits).then(dir))
}
@ -291,8 +291,8 @@ macro_rules! fixed_cmp_float {
return !rhs_is_neg;
}
let rhs_bits = match rhs_128 {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
};
let lhs_bits = self.to_bits();
lhs_bits < rhs_bits || (lhs_bits == rhs_bits && dir == Ordering::Less)
@ -343,8 +343,8 @@ macro_rules! fixed_cmp_float {
return lhs_is_neg;
}
let lhs_bits = match lhs_128 {
Widest::Unsigned(bits) => bits as <$Fix<Frac> as SealedFixed>::Bits,
Widest::Negative(bits) => bits as <$Fix<Frac> as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as <$Fix<Frac> as Fixed>::Bits,
Widest::Negative(bits) => bits as <$Fix<Frac> as Fixed>::Bits,
};
let rhs_bits = rhs.to_bits();
lhs_bits < rhs_bits || (lhs_bits == rhs_bits && dir == Ordering::Greater)

View File

@ -148,7 +148,7 @@ where
#[inline]
fn fmt_radix2<F, Bits>(num: F, radix: &dyn Radix2, fmt: &mut Formatter) -> FmtResult
where
F: SealedFixed<Bits = Bits>,
F: SealedFixed<SBits = Bits>,
Bits: SealedInt,
Bits::Unsigned: FmtRadix2Helper,
{
@ -368,7 +368,7 @@ where
#[inline]
fn fmt_dec<F, Bits>(num: F, fmt: &mut Formatter) -> FmtResult
where
F: SealedFixed<Bits = Bits>,
F: SealedFixed<SBits = Bits>,
Bits: SealedInt,
Bits::Unsigned: FmtDecHelper,
{

View File

@ -224,11 +224,12 @@ use {
},
};
/// A "prelude" for users of the *fixed* crate.
/// A prelude for users of the *fixed* crate.
///
/// This prelude is similar to the standard library's prelude in that you'll
/// almost always want to import its entire contents, but unlike the standard
/// library's prelude you'll have to do so manually:
/// This prelude is similar to the [standard librarys
/// prelude][prelude] in that youll almost always want to import its
/// entire contents, but unlike the standard librarys prelude youll
/// have to do so manually:
///
/// ```
/// ##[allow(unused_imports)]
@ -236,8 +237,13 @@ use {
/// ```
///
/// The prelude may grow over time as additional items see ubiquitous use.
///
/// [prelude]: https://doc.rust-lang.org/nightly/std/prelude/index.html
pub mod prelude {
pub use crate::traits::{FromFixed, ToFixed};
pub use crate::{
sealed::Fixed,
traits::{FromFixed, ToFixed},
};
}
#[macro_use]

View File

@ -56,7 +56,7 @@ assert_eq!((-two_and_quarter).int(), -three);
";
#[inline]
pub fn int(self) -> $Fixed<Frac> {
let mask = Self::INT_MASK as <Self as SealedFixed>::Bits;
let mask = Self::INT_MASK as <Self as Fixed>::Bits;
Self::from_bits(self.to_bits() & mask)
}
);
@ -102,7 +102,7 @@ assert_eq!((-two_and_quarter).frac(), three_quarters);
";
#[inline]
pub fn frac(self) -> $Fixed<Frac> {
let mask = Self::FRAC_MASK as <Self as SealedFixed>::Bits;
let mask = Self::FRAC_MASK as <Self as Fixed>::Bits;
Self::from_bits(self.to_bits() & mask)
}
);
@ -562,7 +562,7 @@ assert_eq!(two_half.overflowing_ceil(), (Fix::from_int(3), false));
if Self::INT_NBITS == 0 {
return (int, self.to_bits() > 0);
}
let int_lsb = Self::INT_LSB as <Self as SealedFixed>::Bits;
let int_lsb = Self::INT_LSB as <Self as Fixed>::Bits;
let increment = Self::from_bits(int_lsb);
if_signed! {
$Signedness;
@ -652,11 +652,11 @@ assert_eq!(two_half.overflowing_round(), (Fix::from_int(3), false));
#[inline]
pub fn overflowing_round(self) -> ($Fixed<Frac>, bool) {
let int = self.int();
let frac_msb = Self::FRAC_MSB as <Self as SealedFixed>::Bits;
let frac_msb = Self::FRAC_MSB as <Self as Fixed>::Bits;
if (self.to_bits() & frac_msb) == 0 {
return (int, false);
}
let int_lsb = Self::INT_LSB as <Self as SealedFixed>::Bits;
let int_lsb = Self::INT_LSB as <Self as Fixed>::Bits;
let increment = Self::from_bits(int_lsb);
if_signed! {
$Signedness;

View File

@ -50,7 +50,7 @@ use half::f16;
/// [`u64`]: https://doc.rust-lang.org/nightly/std/primitive.u64.html
/// [`u8`]: https://doc.rust-lang.org/nightly/std/primitive.u8.html
/// [`usize`]: https://doc.rust-lang.org/nightly/std/primitive.usize.html
pub trait Int: SealedInt + FromFixed + ToFixed {}
pub trait Int: SealedInt + FromFixed + ToFixed + Copy {}
/// This trait is implemented for the primitive floating-point types,
/// and for [`f16`] if the [`f16` feature] is enabled.
@ -63,7 +63,7 @@ pub trait Int: SealedInt + FromFixed + ToFixed {}
/// [`f32`]: https://doc.rust-lang.org/nightly/std/primitive.f32.html
/// [`f64`]: https://doc.rust-lang.org/nightly/std/primitive.f64.html
/// [`f16` feature]: ../index.html#optional-features
pub trait Float: SealedFloat + FromFixed + ToFixed {}
pub trait Float: SealedFloat + FromFixed + ToFixed + Copy {}
/// This trait is implemented for all the fixed-point types.
///
@ -82,36 +82,16 @@ pub trait Float: SealedFloat + FromFixed + ToFixed {}
/// [`FixedU32`]: ../struct.FixedU32.html
/// [`FixedU64`]: ../struct.FixedU64.html
/// [`FixedU8`]: ../struct.FixedU8.html
pub trait Fixed: SealedFixed + FromFixed + ToFixed {}
pub trait Fixed: SealedFixed + FromFixed + ToFixed + Copy {
/// The primitive integer underlying type.
type Bits: Int;
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 {}
/// Create with a given bit representation.
fn from_bits(bits: Self::Bits) -> Self;
#[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> {}
/// Convert to a bit representation.
fn to_bits(self) -> Self::Bits;
}
impl ToFixed for bool {
#[inline]
@ -151,8 +131,10 @@ impl ToFixed for bool {
}
}
macro_rules! checked_int {
($Int:ty) => {
macro_rules! impl_int {
($Int:ident) => {
impl Int for $Int {}
impl FromFixed for $Int {
#[inline]
fn from_fixed<F>(val: F) -> Self
@ -231,21 +213,23 @@ macro_rules! checked_int {
};
}
checked_int! { i8 }
checked_int! { i16 }
checked_int! { i32 }
checked_int! { i64 }
checked_int! { i128 }
checked_int! { isize }
checked_int! { u8 }
checked_int! { u16 }
checked_int! { u32 }
checked_int! { u64 }
checked_int! { u128 }
checked_int! { usize }
impl_int! { i8 }
impl_int! { i16 }
impl_int! { i32 }
impl_int! { i64 }
impl_int! { i128 }
impl_int! { isize }
impl_int! { u8 }
impl_int! { u16 }
impl_int! { u32 }
impl_int! { u64 }
impl_int! { u128 }
impl_int! { usize }
macro_rules! checked_float {
macro_rules! impl_float {
($Float:ty) => {
impl Float for $Float {}
impl FromFixed for $Float {
#[inline]
fn from_fixed<F>(val: F) -> Self
@ -325,12 +309,27 @@ macro_rules! checked_float {
}
#[cfg(feature = "f16")]
checked_float! { f16 }
checked_float! { f32 }
checked_float! { f64 }
impl_float! { f16 }
impl_float! { f32 }
impl_float! { f64 }
macro_rules! impl_fixed {
($Fixed:ident, $NBits:ident, $Bits:ident) => {
impl<Frac> Fixed for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$NBits, Output = True>,
{
type Bits = $Bits;
#[inline]
fn from_bits(bits: Self::Bits) -> Self {
$Fixed::from_bits(bits)
}
#[inline]
fn to_bits(self) -> Self::Bits {
self.to_bits()
}
}
macro_rules! checked_fixed {
($Fixed:ident, $NBits:ident) => {
impl<Frac> FromFixed for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$NBits, Output = True>,
@ -415,13 +414,13 @@ macro_rules! checked_fixed {
};
}
checked_fixed! { FixedI8, U8 }
checked_fixed! { FixedI16, U16 }
checked_fixed! { FixedI32, U32 }
checked_fixed! { FixedI64, U64 }
checked_fixed! { FixedI128, U128 }
checked_fixed! { FixedU8, U8 }
checked_fixed! { FixedU16, U16 }
checked_fixed! { FixedU32, U32 }
checked_fixed! { FixedU64, U64 }
checked_fixed! { FixedU128, U128 }
impl_fixed! { FixedI8, U8, i8 }
impl_fixed! { FixedI16, U16, i16 }
impl_fixed! { FixedI32, U32, i32 }
impl_fixed! { FixedI64, U64, i64 }
impl_fixed! { FixedI128, U128, i128 }
impl_fixed! { FixedU8, U8, u8 }
impl_fixed! { FixedU16, U16, u16 }
impl_fixed! { FixedU32, U32, u32 }
impl_fixed! { FixedU64, U64, u64 }
impl_fixed! { FixedU128, U128, u128 }

View File

@ -35,10 +35,10 @@ pub enum Widest {
pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
type FracNBits: Unsigned;
type Bits: SealedInt;
type SBits: SealedInt;
const FRAC_NBITS: u32 = Self::FracNBits::U32;
const INT_NBITS: u32 = Self::Bits::NBITS - Self::FRAC_NBITS;
const INT_NBITS: u32 = Self::SBits::NBITS - Self::FRAC_NBITS;
const FRAC_MASK: u128 = !Self::INT_MASK;
// split shift in two parts in case that FRAC_NBITS == 128
@ -96,31 +96,33 @@ pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
#[inline]
fn one() -> Option<Self> {
let min_int_bits = if Self::Bits::IS_SIGNED { 2 } else { 1 };
let min_int_bits = if Self::SBits::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)))
Some(Self::from_sbits(Self::SBits::one_shl(Self::FRAC_NBITS)))
}
}
#[inline]
fn minus_one() -> Option<Self> {
if !Self::Bits::IS_SIGNED || Self::INT_NBITS < 1 {
if !Self::SBits::IS_SIGNED || Self::INT_NBITS < 1 {
None
} else {
Some(Self::from_bits(Self::Bits::all_ones_shl(Self::FRAC_NBITS)))
Some(Self::from_sbits(Self::SBits::all_ones_shl(
Self::FRAC_NBITS,
)))
}
}
fn from_bits(bits: Self::Bits) -> Self;
fn to_bits(self) -> Self::Bits;
fn from_sbits(bits: Self::SBits) -> Self;
fn to_sbits(self) -> Self::SBits;
fn parts(
self,
) -> (
bool,
<Self::Bits as SealedInt>::Unsigned,
<Self::Bits as SealedInt>::Unsigned,
<Self::SBits as SealedInt>::Unsigned,
<Self::SBits as SealedInt>::Unsigned,
);
fn wrapping_ceil(self) -> Self;
@ -137,7 +139,7 @@ macro_rules! sealed_fixed {
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
type FracNBits = Frac;
type Bits = $Bits;
type SBits = $Bits;
#[inline]
fn saturating_from_fixed<F>(val: F) -> Self
@ -151,30 +153,30 @@ macro_rules! sealed_fixed {
);
if overflow {
return if val.to_bits().is_negative() {
Self::from_bits(Self::Bits::min_value())
Fixed::from_bits(Self::SBits::min_value())
} else {
Self::from_bits(Self::Bits::max_value())
Fixed::from_bits(Self::SBits::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());
if (bits as Self::SBits) < 0 {
return Fixed::from_bits(Self::SBits::max_value());
}
bits as Self::Bits
bits as Self::SBits
}
Widest::Negative(bits) => bits as Self::Bits,
Widest::Negative(bits) => bits as Self::SBits,
},
match value {
Widest::Unsigned(bits) => bits as Self::Bits,
Widest::Unsigned(bits) => bits as Self::SBits,
Widest::Negative(_) => {
return Self::from_bits(Self::Bits::min_value());
return Fixed::from_bits(Self::SBits::min_value());
}
},
);
SealedFixed::from_bits(bits)
Fixed::from_bits(bits)
}
#[inline]
@ -191,22 +193,22 @@ macro_rules! sealed_fixed {
$Signedness,
match value {
Widest::Unsigned(bits) => {
if (bits as Self::Bits) < 0 {
if (bits as Self::SBits) < 0 {
overflow = true;
}
bits as Self::Bits
bits as Self::SBits
}
Widest::Negative(bits) => bits as Self::Bits,
Widest::Negative(bits) => bits as Self::SBits,
},
match value {
Widest::Unsigned(bits) => bits as Self::Bits,
Widest::Unsigned(bits) => bits as Self::SBits,
Widest::Negative(bits) => {
overflow = true;
bits as Self::Bits
bits as Self::SBits
}
},
);
(SealedFixed::from_bits(bits), overflow)
(Fixed::from_bits(bits), overflow)
}
#[inline]
@ -234,19 +236,19 @@ macro_rules! sealed_fixed {
$Signedness,
match value {
Widest::Unsigned(bits) => {
if (bits as <Self as SealedFixed>::Bits) < 0 {
if (bits as Self::SBits) < 0 {
return Self::max_value();
}
bits as <Self as SealedFixed>::Bits
bits as Self::SBits
}
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as Self::SBits,
},
match value {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as Self::SBits,
Widest::Negative(_) => return Self::min_value(),
},
);
SealedFixed::from_bits(bits)
Fixed::from_bits(bits)
}
#[inline]
fn overflowing_from_float<F>(val: F) -> (Self, bool)
@ -262,22 +264,22 @@ macro_rules! sealed_fixed {
$Signedness,
match value {
Widest::Unsigned(bits) => {
if (bits as <Self as SealedFixed>::Bits) < 0 {
if (bits as Self::SBits) < 0 {
overflow = true;
}
bits as <Self as SealedFixed>::Bits
bits as Self::SBits
}
Widest::Negative(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Negative(bits) => bits as Self::SBits,
},
match value {
Widest::Unsigned(bits) => bits as <Self as SealedFixed>::Bits,
Widest::Unsigned(bits) => bits as Self::SBits,
Widest::Negative(bits) => {
overflow = true;
bits as <Self as SealedFixed>::Bits
bits as Self::SBits
}
},
);
(SealedFixed::from_bits(bits), overflow)
(Fixed::from_bits(bits), overflow)
}
#[inline]
@ -290,12 +292,12 @@ macro_rules! sealed_fixed {
}
#[inline]
fn from_bits(bits: Self::Bits) -> Self {
fn from_sbits(bits: Self::SBits) -> Self {
$Fixed::from_bits(bits)
}
#[inline]
fn to_bits(self) -> Self::Bits {
fn to_sbits(self) -> Self::SBits {
$Fixed::to_bits(self)
}
@ -304,8 +306,8 @@ macro_rules! sealed_fixed {
self,
) -> (
bool,
<Self::Bits as SealedInt>::Unsigned,
<Self::Bits as SealedInt>::Unsigned,
<Self::SBits as SealedInt>::Unsigned,
<Self::SBits as SealedInt>::Unsigned,
) {
let (neg, abs) = SealedInt::neg_abs(self.to_bits());
let (int_abs, frac_abs) = if Self::INT_NBITS == 0 {